From 54c7a4294991fce66e2d921dfd32d075ea616de7 Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Tue, 28 Feb 2012 16:09:15 +0200 Subject: [PATCH] 7143614: SynthLookAndFeel stability improvement Reviewed-by: malenkov --- .../javax/swing/plaf/synth/SynthButtonUI.java | 4 +- .../javax/swing/plaf/synth/SynthLabelUI.java | 4 +- .../swing/plaf/synth/SynthLookAndFeel.java | 57 ++++++----- .../swing/plaf/synth/7143614/bug7143614.java | 97 +++++++++++++++++++ 4 files changed, 133 insertions(+), 29 deletions(-) create mode 100644 jdk/test/javax/swing/plaf/synth/7143614/bug7143614.java diff --git a/jdk/src/share/classes/javax/swing/plaf/synth/SynthButtonUI.java b/jdk/src/share/classes/javax/swing/plaf/synth/SynthButtonUI.java index 80d3eb15fe0..0f5df434c70 100644 --- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthButtonUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthButtonUI.java @@ -152,8 +152,8 @@ public class SynthButtonUI extends BasicButtonUI implements if (!c.isEnabled()) { state = DISABLED; } - if (SynthLookAndFeel.selectedUI == this) { - return SynthLookAndFeel.selectedUIState | SynthConstants.ENABLED; + if (SynthLookAndFeel.getSelectedUI() == this) { + return SynthLookAndFeel.getSelectedUIState() | SynthConstants.ENABLED; } AbstractButton button = (AbstractButton) c; ButtonModel model = button.getModel(); diff --git a/jdk/src/share/classes/javax/swing/plaf/synth/SynthLabelUI.java b/jdk/src/share/classes/javax/swing/plaf/synth/SynthLabelUI.java index 1c1927291b8..e0c50e166cd 100644 --- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthLabelUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthLabelUI.java @@ -97,9 +97,9 @@ public class SynthLabelUI extends BasicLabelUI implements SynthUI { private int getComponentState(JComponent c) { int state = SynthLookAndFeel.getComponentState(c); - if (SynthLookAndFeel.selectedUI == this && + if (SynthLookAndFeel.getSelectedUI() == this && state == SynthConstants.ENABLED) { - state = SynthLookAndFeel.selectedUIState | SynthConstants.ENABLED; + state = SynthLookAndFeel.getSelectedUIState() | SynthConstants.ENABLED; } return state; } diff --git a/jdk/src/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java b/jdk/src/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java index 12121cc5038..bece289030f 100644 --- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java @@ -76,28 +76,26 @@ public class SynthLookAndFeel extends BasicLookAndFeel { private static final Object STYLE_FACTORY_KEY = new StringBuffer("com.sun.java.swing.plaf.gtk.StyleCache"); + /** + * AppContext key to get selectedUI. + */ + private static final Object SELECTED_UI_KEY = new StringBuilder("selectedUI"); + + /** + * AppContext key to get selectedUIState. + */ + private static final Object SELECTED_UI_STATE_KEY = new StringBuilder("selectedUIState"); + /** * The last SynthStyleFactory that was asked for from AppContext * lastContext. */ private static SynthStyleFactory lastFactory; - /** - * If this is true it indicates there is more than one AppContext active - * and that we need to make sure in getStyleCache the requesting - * AppContext matches that of lastContext before returning - * it. - */ - private static boolean multipleApps; /** * AppContext lastLAF came from. */ private static AppContext lastContext; - // Refer to setSelectedUI - static ComponentUI selectedUI; - // Refer to setSelectedUI - static int selectedUIState; - /** * SynthStyleFactory for the this SynthLookAndFeel. */ @@ -111,6 +109,10 @@ public class SynthLookAndFeel extends BasicLookAndFeel { private Handler _handler; + static ComponentUI getSelectedUI() { + return (ComponentUI) AppContext.getAppContext().get(SELECTED_UI_KEY); + } + /** * Used by the renderers. For the most part the renderers are implemented * as Labels, which is problematic in so far as they are never selected. @@ -122,8 +124,8 @@ public class SynthLookAndFeel extends BasicLookAndFeel { static void setSelectedUI(ComponentUI uix, boolean selected, boolean focused, boolean enabled, boolean rollover) { - selectedUI = uix; - selectedUIState = 0; + int selectedUIState = 0; + if (selected) { selectedUIState = SynthConstants.SELECTED; if (focused) { @@ -140,19 +142,32 @@ public class SynthLookAndFeel extends BasicLookAndFeel { else { if (enabled) { selectedUIState |= SynthConstants.ENABLED; - selectedUIState = SynthConstants.FOCUSED; + if (focused) { + selectedUIState |= SynthConstants.FOCUSED; + } } else { selectedUIState |= SynthConstants.DISABLED; } } + + AppContext context = AppContext.getAppContext(); + + context.put(SELECTED_UI_KEY, uix); + context.put(SELECTED_UI_STATE_KEY, Integer.valueOf(selectedUIState)); + } + + static int getSelectedUIState() { + Integer result = (Integer) AppContext.getAppContext().get(SELECTED_UI_STATE_KEY); + + return result == null ? 0 : result.intValue(); } /** * Clears out the selected UI that was last set in setSelectedUI. */ static void resetSelectedUI() { - selectedUI = null; + AppContext.getAppContext().remove(SELECTED_UI_KEY); } @@ -167,10 +182,6 @@ public class SynthLookAndFeel extends BasicLookAndFeel { // for a particular AppContext. synchronized(SynthLookAndFeel.class) { AppContext context = AppContext.getAppContext(); - if (!multipleApps && context != lastContext && - lastContext != null) { - multipleApps = true; - } lastFactory = cache; lastContext = context; context.put(STYLE_FACTORY_KEY, cache); @@ -184,17 +195,13 @@ public class SynthLookAndFeel extends BasicLookAndFeel { */ public static SynthStyleFactory getStyleFactory() { synchronized(SynthLookAndFeel.class) { - if (!multipleApps) { - return lastFactory; - } AppContext context = AppContext.getAppContext(); if (lastContext == context) { return lastFactory; } lastContext = context; - lastFactory = (SynthStyleFactory)AppContext.getAppContext().get - (STYLE_FACTORY_KEY); + lastFactory = (SynthStyleFactory) context.get(STYLE_FACTORY_KEY); return lastFactory; } } diff --git a/jdk/test/javax/swing/plaf/synth/7143614/bug7143614.java b/jdk/test/javax/swing/plaf/synth/7143614/bug7143614.java new file mode 100644 index 00000000000..a4f81fd031e --- /dev/null +++ b/jdk/test/javax/swing/plaf/synth/7143614/bug7143614.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7143614 + * @summary Issues with Synth Look&Feel + * @author Pavel Porvatov + */ + +import sun.awt.SunToolkit; + +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicButtonUI; +import javax.swing.plaf.synth.SynthConstants; +import javax.swing.plaf.synth.SynthLookAndFeel; +import java.lang.reflect.Method; + +public class bug7143614 { + private static Method setSelectedUIMethod; + + private static ComponentUI componentUI = new BasicButtonUI(); + + public static void main(String[] args) throws Exception { + setSelectedUIMethod = SynthLookAndFeel.class.getDeclaredMethod("setSelectedUI", ComponentUI.class, + boolean.class, boolean.class, boolean.class, boolean.class); + setSelectedUIMethod.setAccessible(true); + + setSelectedUIMethod.invoke(null, componentUI, true, true, true, true); + + validate(); + + Thread thread = new ThreadInAnotherAppContext(); + + thread.start(); + thread.join(); + + validate(); + + System.out.println("Test bug7143614 passed."); + } + + private static void validate() throws Exception { + Method getSelectedUIMethod = SynthLookAndFeel.class.getDeclaredMethod("getSelectedUI"); + + getSelectedUIMethod.setAccessible(true); + + Method getSelectedUIStateMethod = SynthLookAndFeel.class.getDeclaredMethod("getSelectedUIState"); + + getSelectedUIStateMethod.setAccessible(true); + + if (getSelectedUIMethod.invoke(null) != componentUI) { + throw new RuntimeException("getSelectedUI returns invalid value"); + } + if (((Integer) getSelectedUIStateMethod.invoke(null)).intValue() != + (SynthConstants.SELECTED | SynthConstants.FOCUSED)) { + throw new RuntimeException("getSelectedUIState returns invalid value"); + } + + } + + private static class ThreadInAnotherAppContext extends Thread { + public ThreadInAnotherAppContext() { + super(new ThreadGroup("7143614"), "ThreadInAnotherAppContext"); + } + + public void run() { + SunToolkit.createNewAppContext(); + + try { + setSelectedUIMethod.invoke(null, null, false, false, false, false); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } +}