jdk/src/share/classes/com/sun/awt/AWTUtilities.java
changeset 2451 597df8e1d786
parent 1978 8b981ce05cd0
child 3237 7c6c2d9361d9
equal deleted inserted replaced
1978:8b981ce05cd0 2451:597df8e1d786
     1 /*
     1 /*
     2  * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
     2  * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Sun designates this
     7  * published by the Free Software Foundation.  Sun designates this
    24  */
    24  */
    25 
    25 
    26 package com.sun.awt;
    26 package com.sun.awt;
    27 
    27 
    28 import java.awt.*;
    28 import java.awt.*;
       
    29 
    29 import sun.awt.AWTAccessor;
    30 import sun.awt.AWTAccessor;
    30 
    31 import sun.awt.SunToolkit;
    31 
    32 
    32 /**
    33 /**
    33  * A collection of utility methods for AWT.
    34  * A collection of utility methods for AWT.
    34  *
    35  *
    35  * The functionality provided by the static methods of the class includes:
    36  * The functionality provided by the static methods of the class includes:
    36  * <ul>
    37  * <ul>
       
    38  * <li>Setting shapes on top-level windows
       
    39  * <li>Setting a constant alpha value for each pixel of a top-level window
       
    40  * <li>Making a window non-opaque, after that it paints only explicitly
       
    41  * painted pixels on the screen, with arbitrary alpha values for every pixel.
    37  * <li>Setting a 'mixing-cutout' shape for a component.
    42  * <li>Setting a 'mixing-cutout' shape for a component.
    38  * </ul>
    43  * </ul>
       
    44  * <p>
       
    45  * A "top-level window" is an instance of the {@code Window} class (or its
       
    46  * descendant, such as {@code JFrame}).
       
    47  * <p>
       
    48  * Some of the mentioned features may not be supported by the native platform.
       
    49  * To determine whether a particular feature is supported, the user must use
       
    50  * the {@code isTranslucencySupported()} method of the class passing a desired
       
    51  * translucency kind (a member of the {@code Translucency} enum) as an
       
    52  * argument.
       
    53  * <p>
       
    54  * The per-pixel alpha feature also requires the user to create her/his
       
    55  * windows using a translucency-capable graphics configuration.
       
    56  * The {@code isTranslucencyCapable()} method must
       
    57  * be used to verify whether any given GraphicsConfiguration supports
       
    58  * the trasnlcency effects.
    39  * <p>
    59  * <p>
    40  * <b>WARNING</b>: This class is an implementation detail and only meant
    60  * <b>WARNING</b>: This class is an implementation detail and only meant
    41  * for limited use outside of the core platform. This API may change
    61  * for limited use outside of the core platform. This API may change
    42  * drastically between update release, and it may even be
    62  * drastically between update release, and it may even be
    43  * removed or be moved in some other package(s)/class(es).
    63  * removed or be moved in some other package(s)/class(es).
    46 
    66 
    47     /**
    67     /**
    48      * The AWTUtilities class should not be instantiated
    68      * The AWTUtilities class should not be instantiated
    49      */
    69      */
    50     private AWTUtilities() {
    70     private AWTUtilities() {
       
    71     }
       
    72 
       
    73     /** Kinds of translucency supported by the underlying system.
       
    74      *  @see #isTranslucencySupported
       
    75      */
       
    76     public static enum Translucency {
       
    77         /**
       
    78          * Represents support in the underlying system for windows each pixel
       
    79          * of which is guaranteed to be either completely opaque, with
       
    80          * an alpha value of 1.0, or completely transparent, with an alpha
       
    81          * value of 0.0.
       
    82          */
       
    83         PERPIXEL_TRANSPARENT,
       
    84 
       
    85         /**
       
    86          * Represents support in the underlying system for windows all of
       
    87          * the pixels of which have the same alpha value between or including
       
    88          * 0.0 and 1.0.
       
    89          */
       
    90         TRANSLUCENT,
       
    91 
       
    92         /**
       
    93          * Represents support in the underlying system for windows that
       
    94          * contain or might contain pixels with arbitrary alpha values
       
    95          * between and including 0.0 and 1.0.
       
    96          */
       
    97         PERPIXEL_TRANSLUCENT;
       
    98     }
       
    99 
       
   100 
       
   101     /**
       
   102      * Returns whether the given level of translucency is supported by
       
   103      * the underlying system.
       
   104      *
       
   105      * Note that this method may sometimes return the value
       
   106      * indicating that the particular level is supported, but
       
   107      * the native windowing system may still not support the
       
   108      * given level of translucency (due to the bugs in
       
   109      * the windowing system).
       
   110      *
       
   111      * @param translucencyKind a kind of translucency support
       
   112      *                         (either PERPIXEL_TRANSPARENT,
       
   113      *                         TRANSLUCENT, or PERPIXEL_TRANSLUCENT)
       
   114      * @return whether the given translucency kind is supported
       
   115      */
       
   116     public static boolean isTranslucencySupported(Translucency translucencyKind) {
       
   117         switch (translucencyKind) {
       
   118             case PERPIXEL_TRANSPARENT:
       
   119                 return isWindowShapingSupported();
       
   120             case TRANSLUCENT:
       
   121                 return isWindowOpacitySupported();
       
   122             case PERPIXEL_TRANSLUCENT:
       
   123                 return isWindowTranslucencySupported();
       
   124         }
       
   125         return false;
       
   126     }
       
   127 
       
   128 
       
   129     /**
       
   130      * Returns whether the windowing system supports changing the opacity
       
   131      * value of top-level windows.
       
   132      * Note that this method may sometimes return true, but the native
       
   133      * windowing system may still not support the concept of
       
   134      * translucency (due to the bugs in the windowing system).
       
   135      */
       
   136     private static boolean isWindowOpacitySupported() {
       
   137         Toolkit curToolkit = Toolkit.getDefaultToolkit();
       
   138         if (!(curToolkit instanceof SunToolkit)) {
       
   139             return false;
       
   140         }
       
   141         return ((SunToolkit)curToolkit).isWindowOpacitySupported();
       
   142     }
       
   143 
       
   144     /**
       
   145      * Set the opacity of the window. The opacity is at the range [0..1].
       
   146      * Note that setting the opacity level of 0 may or may not disable
       
   147      * the mouse event handling on this window. This is
       
   148      * a platform-dependent behavior.
       
   149      *
       
   150      * In order for this method to enable the translucency effect,
       
   151      * the isTranslucencySupported() method should indicate that the
       
   152      * TRANSLUCENT level of translucency is supported.
       
   153      *
       
   154      * <p>Also note that the window must not be in the full-screen mode
       
   155      * when setting the opacity value &lt; 1.0f. Otherwise
       
   156      * the IllegalArgumentException is thrown.
       
   157      *
       
   158      * @param window the window to set the opacity level to
       
   159      * @param opacity the opacity level to set to the window
       
   160      * @throws NullPointerException if the window argument is null
       
   161      * @throws IllegalArgumentException if the opacity is out of
       
   162      *                                  the range [0..1]
       
   163      * @throws IllegalArgumentException if the window is in full screen mode,
       
   164      *                                  and the opacity is less than 1.0f
       
   165      * @throws UnsupportedOperationException if the TRANSLUCENT translucency
       
   166      *                                       kind is not supported
       
   167      */
       
   168     public static void setWindowOpacity(Window window, float opacity) {
       
   169         if (window == null) {
       
   170             throw new NullPointerException(
       
   171                     "The window argument should not be null.");
       
   172         }
       
   173 
       
   174         AWTAccessor.getWindowAccessor().setOpacity(window, opacity);
       
   175     }
       
   176 
       
   177     /**
       
   178      * Get the opacity of the window. If the opacity has not
       
   179      * yet being set, this method returns 1.0.
       
   180      *
       
   181      * @param window the window to get the opacity level from
       
   182      * @throws NullPointerException if the window argument is null
       
   183      */
       
   184     public static float getWindowOpacity(Window window) {
       
   185         if (window == null) {
       
   186             throw new NullPointerException(
       
   187                     "The window argument should not be null.");
       
   188         }
       
   189 
       
   190         return AWTAccessor.getWindowAccessor().getOpacity(window);
       
   191     }
       
   192 
       
   193     /**
       
   194      * Returns whether the windowing system supports changing the shape
       
   195      * of top-level windows.
       
   196      * Note that this method may sometimes return true, but the native
       
   197      * windowing system may still not support the concept of
       
   198      * shaping (due to the bugs in the windowing system).
       
   199      */
       
   200     public static boolean isWindowShapingSupported() {
       
   201         Toolkit curToolkit = Toolkit.getDefaultToolkit();
       
   202         if (!(curToolkit instanceof SunToolkit)) {
       
   203             return false;
       
   204         }
       
   205         return ((SunToolkit)curToolkit).isWindowShapingSupported();
       
   206     }
       
   207 
       
   208     /**
       
   209      * Returns an object that implements the Shape interface and represents
       
   210      * the shape previously set with the call to the setWindowShape() method.
       
   211      * If no shape has been set yet, or the shape has been reset to null,
       
   212      * this method returns null.
       
   213      *
       
   214      * @param window the window to get the shape from
       
   215      * @return the current shape of the window
       
   216      * @throws NullPointerException if the window argument is null
       
   217      */
       
   218     public static Shape getWindowShape(Window window) {
       
   219         if (window == null) {
       
   220             throw new NullPointerException(
       
   221                     "The window argument should not be null.");
       
   222         }
       
   223         return AWTAccessor.getWindowAccessor().getShape(window);
       
   224     }
       
   225 
       
   226     /**
       
   227      * Sets a shape for the given window.
       
   228      * If the shape argument is null, this methods restores
       
   229      * the default shape making the window rectangular.
       
   230      * <p>Note that in order to set a shape, the window must be undecorated.
       
   231      * If the window is decorated, this method ignores the {@code shape}
       
   232      * argument and resets the shape to null.
       
   233      * <p>Also note that the window must not be in the full-screen mode
       
   234      * when setting a non-null shape. Otherwise the IllegalArgumentException
       
   235      * is thrown.
       
   236      * <p>Depending on the platform, the method may return without
       
   237      * effecting the shape of the window if the window has a non-null warning
       
   238      * string ({@link Window#getWarningString()}). In this case the passed
       
   239      * shape object is ignored.
       
   240      *
       
   241      * @param window the window to set the shape to
       
   242      * @param shape the shape to set to the window
       
   243      * @throws NullPointerException if the window argument is null
       
   244      * @throws IllegalArgumentException if the window is in full screen mode,
       
   245      *                                  and the shape is not null
       
   246      * @throws UnsupportedOperationException if the PERPIXEL_TRANSPARENT
       
   247      *                                       translucency kind is not supported
       
   248      */
       
   249     public static void setWindowShape(Window window, Shape shape) {
       
   250         if (window == null) {
       
   251             throw new NullPointerException(
       
   252                     "The window argument should not be null.");
       
   253         }
       
   254         AWTAccessor.getWindowAccessor().setShape(window, shape);
       
   255     }
       
   256 
       
   257     private static boolean isWindowTranslucencySupported() {
       
   258         /*
       
   259          * Per-pixel alpha is supported if all the conditions are TRUE:
       
   260          *    1. The toolkit is a sort of SunToolkit
       
   261          *    2. The toolkit supports translucency in general
       
   262          *        (isWindowTranslucencySupported())
       
   263          *    3. There's at least one translucency-capable
       
   264          *        GraphicsConfiguration
       
   265          */
       
   266 
       
   267         Toolkit curToolkit = Toolkit.getDefaultToolkit();
       
   268         if (!(curToolkit instanceof SunToolkit)) {
       
   269             return false;
       
   270         }
       
   271 
       
   272         if (!((SunToolkit)curToolkit).isWindowTranslucencySupported()) {
       
   273             return false;
       
   274         }
       
   275 
       
   276         GraphicsEnvironment env =
       
   277             GraphicsEnvironment.getLocalGraphicsEnvironment();
       
   278 
       
   279         // If the default GC supports translucency return true.
       
   280         // It is important to optimize the verification this way,
       
   281         // see CR 6661196 for more details.
       
   282         if (isTranslucencyCapable(env.getDefaultScreenDevice()
       
   283                     .getDefaultConfiguration()))
       
   284         {
       
   285             return true;
       
   286         }
       
   287 
       
   288         // ... otherwise iterate through all the GCs.
       
   289         GraphicsDevice[] devices = env.getScreenDevices();
       
   290 
       
   291         for (int i = 0; i < devices.length; i++) {
       
   292             GraphicsConfiguration[] configs = devices[i].getConfigurations();
       
   293             for (int j = 0; j < configs.length; j++) {
       
   294                 if (isTranslucencyCapable(configs[j])) {
       
   295                     return true;
       
   296                 }
       
   297             }
       
   298         }
       
   299 
       
   300         return false;
       
   301     }
       
   302 
       
   303     /**
       
   304      * Enables the per-pixel alpha support for the given window.
       
   305      * Once the window becomes non-opaque (the isOpaque is set to false),
       
   306      * the drawing sub-system is starting to respect the alpha value of each
       
   307      * separate pixel. If a pixel gets painted with alpha color component
       
   308      * equal to zero, it becomes visually transparent, if the alpha of the
       
   309      * pixel is equal to 255, the pixel is fully opaque. Interim values
       
   310      * of the alpha color component make the pixel semi-transparent (i.e.
       
   311      * translucent).
       
   312      * <p>Note that in order for the window to support the per-pixel alpha
       
   313      * mode, the window must be created using the GraphicsConfiguration
       
   314      * for which the {@link #isTranslucencyCapable}
       
   315      * method returns true.
       
   316      * <p>Also note that some native systems enable the per-pixel translucency
       
   317      * mode for any window created using the translucency-compatible
       
   318      * graphics configuration. However, it is highly recommended to always
       
   319      * invoke the setWindowOpaque() method for these windows, at least for
       
   320      * the sake of cross-platform compatibility reasons.
       
   321      * <p>Also note that the window must not be in the full-screen mode
       
   322      * when making it non-opaque. Otherwise the IllegalArgumentException
       
   323      * is thrown.
       
   324      * <p>If the window is a {@code Frame} or a {@code Dialog}, the window must
       
   325      * be undecorated prior to enabling the per-pixel translucency effect (see
       
   326      * {@link Frame#setUndecorated()} and/or {@link Dialog#setUndecorated()}).
       
   327      * If the window becomes decorated through a subsequent call to the
       
   328      * corresponding {@code setUndecorated()} method, the per-pixel
       
   329      * translucency effect will be disabled and the opaque property reset to
       
   330      * {@code true}.
       
   331      * <p>Depending on the platform, the method may return without
       
   332      * effecting the opaque property of the window if the window has a non-null
       
   333      * warning string ({@link Window#getWarningString()}). In this case
       
   334      * the passed 'isOpaque' value is ignored.
       
   335      *
       
   336      * @param window the window to set the shape to
       
   337      * @param isOpaque whether the window must be opaque (true),
       
   338      *                 or translucent (false)
       
   339      * @throws NullPointerException if the window argument is null
       
   340      * @throws IllegalArgumentException if the window uses
       
   341      *                                  a GraphicsConfiguration for which the
       
   342      *                                  {@code isTranslucencyCapable()}
       
   343      *                                  method returns false
       
   344      * @throws IllegalArgumentException if the window is in full screen mode,
       
   345      *                                  and the isOpaque is false
       
   346      * @throws IllegalArgumentException if the window is decorated and the
       
   347      * isOpaque argument is {@code false}.
       
   348      * @throws UnsupportedOperationException if the PERPIXEL_TRANSLUCENT
       
   349      *                                       translucency kind is not supported
       
   350      */
       
   351     public static void setWindowOpaque(Window window, boolean isOpaque) {
       
   352         if (window == null) {
       
   353             throw new NullPointerException(
       
   354                     "The window argument should not be null.");
       
   355         }
       
   356         if (!isOpaque && !isTranslucencySupported(Translucency.PERPIXEL_TRANSLUCENT)) {
       
   357             throw new UnsupportedOperationException(
       
   358                     "The PERPIXEL_TRANSLUCENT translucency kind is not supported");
       
   359         }
       
   360         AWTAccessor.getWindowAccessor().setOpaque(window, isOpaque);
       
   361     }
       
   362 
       
   363     /**
       
   364      * Returns whether the window is opaque or translucent.
       
   365      *
       
   366      * @param window the window to set the shape to
       
   367      * @return whether the window is currently opaque (true)
       
   368      *         or translucent (false)
       
   369      * @throws NullPointerException if the window argument is null
       
   370      */
       
   371     public static boolean isWindowOpaque(Window window) {
       
   372         if (window == null) {
       
   373             throw new NullPointerException(
       
   374                     "The window argument should not be null.");
       
   375         }
       
   376 
       
   377         return AWTAccessor.getWindowAccessor().isOpaque(window);
       
   378     }
       
   379 
       
   380     /**
       
   381      * Verifies whether a given GraphicsConfiguration supports
       
   382      * the PERPIXEL_TRANSLUCENT kind of translucency.
       
   383      * All windows that are intended to be used with the {@link #setWindowOpaque}
       
   384      * method must be created using a GraphicsConfiguration for which this method
       
   385      * returns true.
       
   386      * <p>Note that some native systems enable the per-pixel translucency
       
   387      * mode for any window created using a translucency-capable
       
   388      * graphics configuration. However, it is highly recommended to always
       
   389      * invoke the setWindowOpaque() method for these windows, at least
       
   390      * for the sake of cross-platform compatibility reasons.
       
   391      *
       
   392      * @param gc GraphicsConfiguration
       
   393      * @throws NullPointerException if the gc argument is null
       
   394      * @return whether the given GraphicsConfiguration supports
       
   395      *         the translucency effects.
       
   396      */
       
   397     public static boolean isTranslucencyCapable(GraphicsConfiguration gc) {
       
   398         if (gc == null) {
       
   399             throw new NullPointerException("The gc argument should not be null");
       
   400         }
       
   401         /*
       
   402         return gc.isTranslucencyCapable();
       
   403         */
       
   404         Toolkit curToolkit = Toolkit.getDefaultToolkit();
       
   405         if (!(curToolkit instanceof SunToolkit)) {
       
   406             return false;
       
   407         }
       
   408         return ((SunToolkit)curToolkit).isTranslucencyCapable(gc);
    51     }
   409     }
    52 
   410 
    53     /**
   411     /**
    54      * Sets a 'mixing-cutout' shape for the given component.
   412      * Sets a 'mixing-cutout' shape for the given component.
    55      *
   413      *