956 lines · 35.5 KB · Java
RawDownload
     * @return true if should use buffering per window in painting.     */    private boolean prepare(JComponent c, boolean isPaint, int x, int y,                            int w, int h) {        if (bsg != null) {            bsg.dispose();            bsg = null;        }        bufferStrategy = null;        if (fetchRoot(c)) {            boolean contentsLost = false;            BufferInfo bufferInfo = getBufferInfo(root);            if (bufferInfo == null) {                contentsLost = true;                bufferInfo = new BufferInfo(root);                bufferInfos.add(bufferInfo);                if (LOGGER.isLoggable(PlatformLogger.FINER)) {                    LOGGER.finer("prepare: new BufferInfo: " + root);                }            }            this.bufferInfo = bufferInfo;            if (!bufferInfo.hasBufferStrategyChanged()) {                bufferStrategy = bufferInfo.getBufferStrategy(true);                if (bufferStrategy != null) {                    bsg = bufferStrategy.getDrawGraphics();                    if (bufferStrategy.contentsRestored()) {                        contentsLost = true;                        if (LOGGER.isLoggable(PlatformLogger.FINER)) {                            LOGGER.finer(                                "prepare: contents restored in prepare");                        }                    }                }                else {                    // Couldn't create BufferStrategy, fallback to normal                    // painting.                    return false;                }                if (bufferInfo.getContentsLostDuringExpose()) {                    contentsLost = true;                    bufferInfo.setContentsLostDuringExpose(false);                    if (LOGGER.isLoggable(PlatformLogger.FINER)) {                        LOGGER.finer("prepare: contents lost on expose");                    }                }                if (isPaint && c == rootJ && x == 0 && y == 0 &&                      c.getWidth() == w && c.getHeight() == h) {                    bufferInfo.setInSync(true);                }                else if (contentsLost) {                    // We either recreated the BufferStrategy, or the contents                    // of the buffer strategy were restored.  We need to                    // repaint the root pane so that the back buffer is in sync                    // again.                    bufferInfo.setInSync(false);                    if (!isRepaintingRoot()) {                        repaintRoot(rootJ);                    }                    else {                        // Contents lost twice in a row, punt                        resetDoubleBufferPerWindow();                    }                }                return (bufferInfos != null);            }        }        return false;    }     private boolean fetchRoot(JComponent c) {        boolean encounteredHW = false;        rootJ = c;        root = c;        xOffset = yOffset = 0;        while (root != null &&               (!(root instanceof Window) &&                !SunToolkit.isInstanceOf(root, "java.applet.Applet"))) {            xOffset += root.getX();            yOffset += root.getY();            root = root.getParent();            if (root != null) {                if (root instanceof JComponent) {                    rootJ = (JComponent)root;                }                else if (!root.isLightweight()) {                    if (!encounteredHW) {                        encounteredHW = true;                    }                    else {                        // We've encountered two hws now and may have                        // a containment hierarchy with lightweights containing                        // heavyweights containing other lightweights.                        // Heavyweights poke holes in lightweight                        // rendering so that if we call show on the BS                        // (which is associated with the Window) you will                        // not see the contents over any child                        // heavyweights.  If we didn't do this when we                        // went to show the descendants of the nested hw                        // you would see nothing, so, we bail out here.                        return false;                    }                }            }        }        if ((root instanceof RootPaneContainer) &&            (rootJ instanceof JRootPane)) {            // We're in a Swing heavyeight (JFrame/JWindow...), use double            // buffering if double buffering enabled on the JRootPane and            // the JRootPane wants true double buffering.            if (rootJ.isDoubleBuffered() &&                    ((JRootPane)rootJ).getUseTrueDoubleBuffering()) {                // Whether or not a component is double buffered is a                // bit tricky with Swing. This gives a good approximation                // of the various ways to turn on double buffering for                // components.                return true;            }        }        // Don't do true double buffering.        return false;    }     /**     * Turns off double buffering per window.     */    private void resetDoubleBufferPerWindow() {        if (bufferInfos != null) {            dispose(bufferInfos);            bufferInfos = null;            repaintManager.setPaintManager(null);        }    }     /**     * Returns the BufferInfo for the specified root or null if one     * hasn't been created yet.     */    private BufferInfo getBufferInfo(Container root) {        for (int counter = bufferInfos.size() - 1; counter >= 0; counter--) {            BufferInfo bufferInfo = bufferInfos.get(counter);            Container biRoot = bufferInfo.getRoot();            if (biRoot == null) {                // Window gc'ed                bufferInfos.remove(counter);                if (LOGGER.isLoggable(PlatformLogger.FINER)) {                    LOGGER.finer("BufferInfo pruned, root null");                }            }            else if (biRoot == root) {                return bufferInfo;            }        }        return null;    }     private void accumulate(int x, int y, int w, int h) {        accumulatedX = Math.min(x, accumulatedX);        accumulatedY = Math.min(y, accumulatedY);        accumulatedMaxX = Math.max(accumulatedMaxX, x + w);        accumulatedMaxY = Math.max(accumulatedMaxY, y + h);    }       /**     * BufferInfo is used to track the BufferStrategy being used for     * a particular Component.  In addition to tracking the BufferStrategy     * it will install a WindowListener and ComponentListener.  When the     * component is hidden/iconified the buffer is marked as needing to be     * completely repainted.     */    private class BufferInfo extends ComponentAdapter implements                               WindowListener {        // NOTE: This class does NOT hold a direct reference to the root, if it        // did there would be a cycle between the BufferPerWindowPaintManager        // and the Window so that it could never be GC'ed        //        // Reference to BufferStrategy is referenced via WeakReference for        // same reason.        private WeakReference<BufferStrategy> weakBS;        private WeakReference<Container> root;        // Indicates whether or not the backbuffer and display are in sync.        // This is set to true when a full repaint on the rootpane is done.        private boolean inSync;        // Indicates the contents were lost during and expose event.        private boolean contentsLostDuringExpose;        // Indicates we need to generate a paint event on expose.        private boolean paintAllOnExpose;          public BufferInfo(Container root) {            this.root = new WeakReference<Container>(root);            root.addComponentListener(this);            if (root instanceof Window) {                ((Window)root).addWindowListener(this);            }        }         public void setPaintAllOnExpose(boolean paintAllOnExpose) {            this.paintAllOnExpose = paintAllOnExpose;        }         public boolean getPaintAllOnExpose() {            return paintAllOnExpose;        }         public void setContentsLostDuringExpose(boolean value) {            contentsLostDuringExpose = value;        }         public boolean getContentsLostDuringExpose() {            return contentsLostDuringExpose;        }         public void setInSync(boolean inSync) {            this.inSync = inSync;        }         /**         * Whether or not the contents of the buffer strategy         * is in sync with the window.  This is set to true when the root         * pane paints all, and false when contents are lost/restored.         */        public boolean isInSync() {            return inSync;        }         /**         * Returns the Root (Window or Applet) that this BufferInfo references.         */        public Container getRoot() {            return (root == null) ? null : root.get();        }         /**         * Returns the BufferStartegy.  This will return null if         * the BufferStartegy hasn't been created and <code>create</code> is         * false, or if there is a problem in creating the         * <code>BufferStartegy</code>.         *         * @param create If true, and the BufferStartegy is currently null,         *               one will be created.         */        public BufferStrategy getBufferStrategy(boolean create) {            BufferStrategy bs = (weakBS == null) ? null : weakBS.get();            if (bs == null && create) {                bs = createBufferStrategy();                if (bs != null) {                    weakBS = new WeakReference<BufferStrategy>(bs);                }                if (LOGGER.isLoggable(PlatformLogger.FINER)) {                    LOGGER.finer("getBufferStrategy: created bs: " + bs);                }            }            return bs;        }         /**         * Returns true if the buffer strategy of the component differs         * from current buffer strategy.         */        public boolean hasBufferStrategyChanged() {            Container root = getRoot();            if (root != null) {                BufferStrategy ourBS = null;                BufferStrategy componentBS = null;                 ourBS = getBufferStrategy(false);                if (root instanceof Window) {                    componentBS = ((Window)root).getBufferStrategy();                }                else {                    try {                        componentBS = (BufferStrategy)                                 getGetBufferStrategyMethod().invoke(root);                    } catch (InvocationTargetException ite) {                        assert false;                    } catch (IllegalArgumentException iae) {                        assert false;                    } catch (IllegalAccessException iae2) {                        assert false;                    }                }                if (componentBS != ourBS) {                    // Component has a different BS, dispose ours.                    if (ourBS != null) {                        ourBS.dispose();                    }                    weakBS = null;                    return true;                }            }            return false;        }         /**         * Creates the BufferStrategy.  If the appropriate system property         * has been set we'll try for flip first and then we'll try for         * blit.         */        private BufferStrategy createBufferStrategy() {            Container root = getRoot();            if (root == null) {                return null;            }            BufferStrategy bs = null;            if (SwingUtilities3.isVsyncRequested(root)) {                bs = createBufferStrategy(root, true);                if (LOGGER.isLoggable(PlatformLogger.FINER)) {                    LOGGER.finer("createBufferStrategy: using vsynced strategy");                }            }            if (bs == null) {                bs = createBufferStrategy(root, false);            }            if (!(bs instanceof SubRegionShowable)) {                // We do this for two reasons:                // 1. So that we know we can cast to SubRegionShowable and                //    invoke show with the minimal region to update                // 2. To avoid the possibility of invoking client code                //    on the toolkit thread.                bs = null;            }            return bs;        }         // Creates and returns a buffer strategy.  If        // there is a problem creating the buffer strategy this will        // eat the exception and return null.        private BufferStrategy createBufferStrategy(Container root,                boolean isVsynced) {            BufferCapabilities caps;            if (isVsynced) {                caps = new ExtendedBufferCapabilities(                    new ImageCapabilities(true), new ImageCapabilities(true),                    BufferCapabilities.FlipContents.COPIED,                    ExtendedBufferCapabilities.VSyncType.VSYNC_ON);            } else {                caps = new BufferCapabilities(                    new ImageCapabilities(true), new ImageCapabilities(true),                    null);            }            BufferStrategy bs = null;            if (SunToolkit.isInstanceOf(root, "java.applet.Applet")) {                try {                    getCreateBufferStrategyMethod().invoke(root, 2, caps);                    bs = (BufferStrategy)getGetBufferStrategyMethod().                                            invoke(root);                } catch (InvocationTargetException ite) {                    // Type is not supported                    if (LOGGER.isLoggable(PlatformLogger.FINER)) {                        LOGGER.finer("createBufferStratety failed",                                     ite);                    }                } catch (IllegalArgumentException iae) {                    assert false;                } catch (IllegalAccessException iae2) {                    assert false;                }            }            else {                try {                    ((Window)root).createBufferStrategy(2, caps);                    bs = ((Window)root).getBufferStrategy();                } catch (AWTException e) {                    // Type not supported                    if (LOGGER.isLoggable(PlatformLogger.FINER)) {                        LOGGER.finer("createBufferStratety failed",                                     e);                    }                }            }            return bs;        }         /**         * Cleans up and removes any references.         */        public void dispose() {            Container root = getRoot();            if (LOGGER.isLoggable(PlatformLogger.FINER)) {                LOGGER.finer("disposed BufferInfo for: " + root);            }            if (root != null) {                root.removeComponentListener(this);                if (root instanceof Window) {                    ((Window)root).removeWindowListener(this);                }                BufferStrategy bs = getBufferStrategy(false);                if (bs != null) {                    bs.dispose();                }            }            this.root = null;            weakBS = null;        }         // We mark the buffer as needing to be painted on a hide/iconify        // because the developer may have conditionalized painting based on        // visibility.        // Ideally we would also move to having the BufferStrategy being        // a SoftReference in Component here, but that requires changes to        // Component and the like.        public void componentHidden(ComponentEvent e) {            Container root = getRoot();            if (root != null && root.isVisible()) {                // This case will only happen if a developer calls                // hide immediately followed by show.  In this case                // the event is delivered after show and the window                // will still be visible.  If a developer altered the                // contents of the window between the hide/show                // invocations we won't recognize we need to paint and                // the contents would be bogus.  Calling repaint here                // fixs everything up.                root.repaint();            }            else {                setPaintAllOnExpose(true);            }        }         public void windowIconified(WindowEvent e) {            setPaintAllOnExpose(true);        }         // On a dispose we chuck everything.        public void windowClosed(WindowEvent e) {            // Make sure we're not showing.            synchronized(BufferStrategyPaintManager.this) {                while (showing) {                    try {                        BufferStrategyPaintManager.this.wait();                    } catch (InterruptedException ie) {                    }                }                bufferInfos.remove(this);            }            dispose();        }         public void windowOpened(WindowEvent e) {        }         public void windowClosing(WindowEvent e) {        }         public void windowDeiconified(WindowEvent e) {        }         public void windowActivated(WindowEvent e) {        }         public void windowDeactivated(WindowEvent e) {        }    }}

Lines 501–956 of 956. Previous lines

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t