7143614: SynthLookAndFeel stability improvement
authorrupashka
Tue, 28 Feb 2012 16:09:15 +0200
changeset 13037 99200b262b30
parent 13036 0fd2665c9314
child 13038 e6024efff1b6
7143614: SynthLookAndFeel stability improvement Reviewed-by: malenkov
jdk/src/share/classes/javax/swing/plaf/synth/SynthButtonUI.java
jdk/src/share/classes/javax/swing/plaf/synth/SynthLabelUI.java
jdk/src/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java
jdk/test/javax/swing/plaf/synth/7143614/bug7143614.java
--- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthButtonUI.java	Tue Feb 28 10:44:56 2012 +0400
+++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthButtonUI.java	Tue Feb 28 16:09:15 2012 +0200
@@ -152,8 +152,8 @@
         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();
--- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthLabelUI.java	Tue Feb 28 10:44:56 2012 +0400
+++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthLabelUI.java	Tue Feb 28 16:09:15 2012 +0200
@@ -97,9 +97,9 @@
 
     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;
     }
--- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java	Tue Feb 28 10:44:56 2012 +0400
+++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java	Tue Feb 28 16:09:15 2012 +0200
@@ -77,27 +77,25 @@
                   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
      * <code>lastContext</code>.
      */
     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 <code>lastContext</code> 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 @@
 
     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 @@
     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 @@
         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 @@
         // 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 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;
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/plaf/synth/7143614/bug7143614.java	Tue Feb 28 16:09:15 2012 +0200
@@ -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);
+            }
+        }
+    }
+}