< prev index next >

modules/graphics/src/main/java/com/sun/javafx/application/PlatformImpl.java

Print this page
rev 9808 : 8131888: Need to deliver javafx.swt as a modular jar in JDK 9


   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.javafx.application;
  27 

  28 import com.sun.javafx.PlatformUtil;
  29 import com.sun.javafx.css.StyleManager;
  30 import com.sun.javafx.runtime.SystemProperties;
  31 import static com.sun.javafx.FXPermissions.CREATE_TRANSPARENT_WINDOW_PERMISSION;



  32 
  33 import java.lang.reflect.InvocationTargetException;
  34 import java.lang.reflect.Method;
  35 import java.security.AccessControlContext;


  36 import java.util.ArrayList;

  37 import java.util.List;


  38 import java.util.Set;
  39 import java.util.concurrent.CopyOnWriteArraySet;
  40 import java.util.concurrent.CountDownLatch;
  41 import java.util.concurrent.atomic.AtomicBoolean;
  42 import java.util.concurrent.atomic.AtomicInteger;

  43 
  44 import javafx.application.Application;
  45 import javafx.application.ConditionalFeature;
  46 
  47 import com.sun.javafx.tk.TKListener;
  48 import com.sun.javafx.tk.TKStage;
  49 import com.sun.javafx.tk.Toolkit;
  50 import javafx.beans.property.BooleanProperty;
  51 import javafx.beans.property.SimpleBooleanProperty;
  52 import javafx.scene.Scene;
  53 
  54 import java.security.AccessController;
  55 import java.security.PrivilegedAction;
  56 
  57 public class PlatformImpl {
  58 
  59     private static AtomicBoolean initialized = new AtomicBoolean(false);
  60     private static AtomicBoolean platformExit = new AtomicBoolean(false);
  61     private static AtomicBoolean toolkitExit = new AtomicBoolean(false);
  62     private static CountDownLatch startupLatch = new CountDownLatch(1);
  63     private static AtomicBoolean listenersRegistered = new AtomicBoolean(false);
  64     private static TKListener toolkitListener = null;
  65     private static volatile boolean implicitExit = true;
  66     private static boolean taskbarApplication = true;
  67     private static boolean contextual2DNavigation;
  68     private static AtomicInteger pendingRunnables = new AtomicInteger(0);
  69     private static AtomicInteger numWindows = new AtomicInteger(0);
  70     private static volatile boolean firstWindowShown = false;
  71     private static volatile boolean lastWindowClosed = false;
  72     private static AtomicBoolean reallyIdle = new AtomicBoolean(false);
  73     private static Set<FinishListener> finishListeners =
  74             new CopyOnWriteArraySet<FinishListener>();
  75     private final static Object runLaterLock = new Object();
  76     private static Boolean isGraphicsSupported;
  77     private static Boolean isControlsSupported;
  78     private static Boolean isMediaSupported;
  79     private static Boolean isWebSupported;
  80     private static Boolean isSWTSupported;
  81     private static Boolean isSwingSupported;
  82     private static Boolean isFXMLSupported;
  83     private static Boolean hasTwoLevelFocus;
  84     private static Boolean hasVirtualKeyboard;
  85     private static Boolean hasTouch;
  86     private static Boolean hasMultiTouch;
  87     private static Boolean hasPointer;
  88     private static boolean isThreadMerged = false;

  89     private static BooleanProperty accessibilityActive = new SimpleBooleanProperty();
  90 




  91     /**
  92      * Set a flag indicating whether this application should show up in the
  93      * task bar. The default value is true.
  94      *
  95      * @param taskbarApplication the new value of this attribute
  96      */
  97     public static void setTaskbarApplication(boolean taskbarApplication) {
  98         PlatformImpl.taskbarApplication = taskbarApplication;
  99     }
 100 
 101     /**
 102      * Returns the current value of the taskBarApplication flag.
 103      *
 104      * @return the current state of the flag.
 105      */
 106     public static boolean isTaskbarApplication() {
 107         return taskbarApplication;
 108     }
 109 
 110     /**


 154     public static void startup(final Runnable r, boolean preventDuplicateCalls) {
 155 
 156         // NOTE: if we ever support re-launching an application and/or
 157         // launching a second application in the same VM/classloader
 158         // this will need to be changed.
 159         if (platformExit.get()) {
 160             throw new IllegalStateException("Platform.exit has been called");
 161         }
 162 
 163         if (initialized.getAndSet(true)) {
 164             if (preventDuplicateCalls) {
 165                 throw new IllegalStateException("Toolkit already initialized");
 166             }
 167 
 168             // If we've already initialized, just put the runnable on the queue.
 169             runLater(r);
 170             return;
 171         }
 172 
 173         AccessController.doPrivileged((PrivilegedAction<Void>) () -> {



 174             contextual2DNavigation = Boolean.getBoolean(
 175                     "com.sun.javafx.isContextual2DNavigation");
 176             String s = System.getProperty("com.sun.javafx.twoLevelFocus");
 177             if (s != null) {
 178                 hasTwoLevelFocus = Boolean.valueOf(s);
 179             }
 180             s = System.getProperty("com.sun.javafx.virtualKeyboard");
 181             if (s != null) {
 182                 if (s.equalsIgnoreCase("none")) {
 183                     hasVirtualKeyboard = false;
 184                 } else if (s.equalsIgnoreCase("javafx")) {
 185                     hasVirtualKeyboard = true;
 186                 } else if (s.equalsIgnoreCase("native")) {
 187                     hasVirtualKeyboard = true;
 188                 }
 189             }
 190             s = System.getProperty("com.sun.javafx.touch");
 191             if (s != null) {
 192                 hasTouch = Boolean.valueOf(s);
 193             }
 194             s = System.getProperty("com.sun.javafx.multiTouch");
 195             if (s != null) {
 196                 hasMultiTouch = Boolean.valueOf(s);
 197             }
 198             s = System.getProperty("com.sun.javafx.pointer");
 199             if (s != null) {
 200                 hasPointer = Boolean.valueOf(s);
 201             }
 202             s = System.getProperty("javafx.embed.singleThread");
 203             if (s != null) {
 204                 isThreadMerged = Boolean.valueOf(s);
 205             }
 206             return null;
 207         });
 208 





 209         if (!taskbarApplication) {
 210             AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
 211                 System.setProperty("glass.taskbarApplication", "false");
 212                 return null;
 213             });
 214         }
 215 
 216         // Create Toolkit listener and register it with the Toolkit.
 217         // Call notifyFinishListeners when we get notified.
 218         toolkitListener = new TKListener() {
 219             @Override public void changedTopLevelWindows(List<TKStage> windows) {
 220                 numWindows.set(windows.size());
 221                 checkIdle();
 222             }
 223 
 224             @Override
 225             public void exitedLastNestedLoop() {
 226                 checkIdle();
 227             }
 228         };
 229         Toolkit.getToolkit().addTkListener(toolkitListener);
 230 
 231         Toolkit.getToolkit().startup(() -> {
 232             startupLatch.countDown();
 233             r.run();
 234         });
 235 
 236         //Initialize the thread merging mechanism
 237         if (isThreadMerged) {
 238             installFwEventQueue();














































































 239         }
 240     }
 241 
 242     private static void installFwEventQueue() {
 243         invokeSwingFXUtilsMethod("installFwEventQueue");
 244     }
 245 
 246     private static void removeFwEventQueue() {
 247         invokeSwingFXUtilsMethod("removeFwEventQueue");
 248     }
 249 
 250     private static void invokeSwingFXUtilsMethod(final String methodName) {
 251         //Use reflection in case we are running compact profile
 252         try {
 253             Class swingFXUtilsClass = Class.forName("javafx.embed.swing.SwingFXUtils");
 254             Method installFwEventQueue = swingFXUtilsClass.getDeclaredMethod(methodName);
 255             AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
 256                 installFwEventQueue.setAccessible(true);
 257                 return null;
 258             });




   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.javafx.application;
  27 
  28 import static com.sun.javafx.FXPermissions.CREATE_TRANSPARENT_WINDOW_PERMISSION;
  29 import com.sun.javafx.PlatformUtil;
  30 import com.sun.javafx.css.StyleManager;
  31 import com.sun.javafx.runtime.SystemProperties;
  32 import com.sun.javafx.tk.TKListener;
  33 import com.sun.javafx.tk.TKStage;
  34 import com.sun.javafx.tk.Toolkit;
  35 import com.sun.javafx.util.ModuleHelper;
  36 
  37 import java.lang.reflect.InvocationTargetException;
  38 import java.lang.reflect.Method;
  39 import java.security.AccessControlContext;
  40 import java.security.AccessController;
  41 import java.security.PrivilegedAction;
  42 import java.util.ArrayList;
  43 import java.util.HashMap;
  44 import java.util.List;
  45 import java.util.Map;
  46 import java.util.Optional;
  47 import java.util.Set;
  48 import java.util.concurrent.CopyOnWriteArraySet;
  49 import java.util.concurrent.CountDownLatch;
  50 import java.util.concurrent.atomic.AtomicBoolean;
  51 import java.util.concurrent.atomic.AtomicInteger;
  52 import java.util.function.Predicate;
  53 
  54 import javafx.application.Application;
  55 import javafx.application.ConditionalFeature;




  56 import javafx.beans.property.BooleanProperty;
  57 import javafx.beans.property.SimpleBooleanProperty;
  58 import javafx.scene.Scene;
  59 import javafx.util.FXPermission;


  60 
  61 public class PlatformImpl {
  62 
  63     private static AtomicBoolean initialized = new AtomicBoolean(false);
  64     private static AtomicBoolean platformExit = new AtomicBoolean(false);
  65     private static AtomicBoolean toolkitExit = new AtomicBoolean(false);
  66     private static CountDownLatch startupLatch = new CountDownLatch(1);
  67     private static AtomicBoolean listenersRegistered = new AtomicBoolean(false);
  68     private static TKListener toolkitListener = null;
  69     private static volatile boolean implicitExit = true;
  70     private static boolean taskbarApplication = true;
  71     private static boolean contextual2DNavigation;
  72     private static AtomicInteger pendingRunnables = new AtomicInteger(0);
  73     private static AtomicInteger numWindows = new AtomicInteger(0);
  74     private static volatile boolean firstWindowShown = false;
  75     private static volatile boolean lastWindowClosed = false;
  76     private static AtomicBoolean reallyIdle = new AtomicBoolean(false);
  77     private static Set<FinishListener> finishListeners =
  78             new CopyOnWriteArraySet<FinishListener>();
  79     private final static Object runLaterLock = new Object();
  80     private static Boolean isGraphicsSupported;
  81     private static Boolean isControlsSupported;
  82     private static Boolean isMediaSupported;
  83     private static Boolean isWebSupported;
  84     private static Boolean isSWTSupported;
  85     private static Boolean isSwingSupported;
  86     private static Boolean isFXMLSupported;
  87     private static Boolean hasTwoLevelFocus;
  88     private static Boolean hasVirtualKeyboard;
  89     private static Boolean hasTouch;
  90     private static Boolean hasMultiTouch;
  91     private static Boolean hasPointer;
  92     private static boolean isThreadMerged = false;
  93     private static String applicationType = "";
  94     private static BooleanProperty accessibilityActive = new SimpleBooleanProperty();
  95 
  96     // Internal permission used by FXCanvas (SWT interop)
  97     private static final FXPermission FXCANVAS_PERMISSION =
  98             new FXPermission("accessFXCanvasInternals");
  99 
 100     /**
 101      * Set a flag indicating whether this application should show up in the
 102      * task bar. The default value is true.
 103      *
 104      * @param taskbarApplication the new value of this attribute
 105      */
 106     public static void setTaskbarApplication(boolean taskbarApplication) {
 107         PlatformImpl.taskbarApplication = taskbarApplication;
 108     }
 109 
 110     /**
 111      * Returns the current value of the taskBarApplication flag.
 112      *
 113      * @return the current state of the flag.
 114      */
 115     public static boolean isTaskbarApplication() {
 116         return taskbarApplication;
 117     }
 118 
 119     /**


 163     public static void startup(final Runnable r, boolean preventDuplicateCalls) {
 164 
 165         // NOTE: if we ever support re-launching an application and/or
 166         // launching a second application in the same VM/classloader
 167         // this will need to be changed.
 168         if (platformExit.get()) {
 169             throw new IllegalStateException("Platform.exit has been called");
 170         }
 171 
 172         if (initialized.getAndSet(true)) {
 173             if (preventDuplicateCalls) {
 174                 throw new IllegalStateException("Toolkit already initialized");
 175             }
 176 
 177             // If we've already initialized, just put the runnable on the queue.
 178             runLater(r);
 179             return;
 180         }
 181 
 182         AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
 183             applicationType = System.getProperty("com.sun.javafx.application.type");
 184             if (applicationType == null) applicationType = "";
 185 
 186             contextual2DNavigation = Boolean.getBoolean(
 187                     "com.sun.javafx.isContextual2DNavigation");
 188             String s = System.getProperty("com.sun.javafx.twoLevelFocus");
 189             if (s != null) {
 190                 hasTwoLevelFocus = Boolean.valueOf(s);
 191             }
 192             s = System.getProperty("com.sun.javafx.virtualKeyboard");
 193             if (s != null) {
 194                 if (s.equalsIgnoreCase("none")) {
 195                     hasVirtualKeyboard = false;
 196                 } else if (s.equalsIgnoreCase("javafx")) {
 197                     hasVirtualKeyboard = true;
 198                 } else if (s.equalsIgnoreCase("native")) {
 199                     hasVirtualKeyboard = true;
 200                 }
 201             }
 202             s = System.getProperty("com.sun.javafx.touch");
 203             if (s != null) {
 204                 hasTouch = Boolean.valueOf(s);
 205             }
 206             s = System.getProperty("com.sun.javafx.multiTouch");
 207             if (s != null) {
 208                 hasMultiTouch = Boolean.valueOf(s);
 209             }
 210             s = System.getProperty("com.sun.javafx.pointer");
 211             if (s != null) {
 212                 hasPointer = Boolean.valueOf(s);
 213             }
 214             s = System.getProperty("javafx.embed.singleThread");
 215             if (s != null) {
 216                 isThreadMerged = Boolean.valueOf(s);
 217             }
 218             return null;
 219         });
 220 
 221         System.err.println("PlatformImpl::startup : applicationType = " + applicationType);
 222         if ("FXCanvas".equals(applicationType)) {
 223             initFXCanvas();
 224         }
 225 
 226         if (!taskbarApplication) {
 227             AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
 228                 System.setProperty("glass.taskbarApplication", "false");
 229                 return null;
 230             });
 231         }
 232 
 233         // Create Toolkit listener and register it with the Toolkit.
 234         // Call notifyFinishListeners when we get notified.
 235         toolkitListener = new TKListener() {
 236             @Override public void changedTopLevelWindows(List<TKStage> windows) {
 237                 numWindows.set(windows.size());
 238                 checkIdle();
 239             }
 240 
 241             @Override
 242             public void exitedLastNestedLoop() {
 243                 checkIdle();
 244             }
 245         };
 246         Toolkit.getToolkit().addTkListener(toolkitListener);
 247 
 248         Toolkit.getToolkit().startup(() -> {
 249             startupLatch.countDown();
 250             r.run();
 251         });
 252 
 253         //Initialize the thread merging mechanism
 254         if (isThreadMerged) {
 255             installFwEventQueue();
 256         }
 257     }
 258 
 259     // Pass certain system properties to glass via the device details Map
 260     private static void initDeviceDetailsFXCanvas() {
 261         // Read the javafx.embed.eventProc system property and store
 262         // it in an entry in the glass Application device details map
 263         final String eventProcProperty = "javafx.embed.eventProc";
 264         final long eventProc = AccessController.doPrivileged((PrivilegedAction<Long>) () ->
 265                 Long.getLong(eventProcProperty, 0));
 266         System.err.println("PlatformImpl.initSWT: "
 267                 + eventProcProperty + " = " + eventProc);
 268         if (eventProc != 0L) {
 269             // Set the value for the javafx.embed.eventProc
 270             // key in the glass Application map
 271             Map map = com.sun.glass.ui.Application.getDeviceDetails();
 272             if (map == null) {
 273                 map = new HashMap();
 274                 com.sun.glass.ui.Application.setDeviceDetails(map);
 275             }
 276             if (map.get(eventProcProperty) == null) {
 277                 map.put(eventProcProperty, eventProc);
 278             }
 279         }
 280     }
 281 
 282     // Add the necessary qualified exports to the calling module
 283     private static void addExportsToFXCanvas(Class<?> fxCanvasClass) {
 284         final String[] swtNeededPackages = {
 285             "com.sun.glass.ui",
 286             "com.sun.javafx.cursor",
 287             "com.sun.javafx.embed",
 288             "com.sun.javafx.stage"
 289         };
 290 
 291         System.err.println("addExportsToFXCanvas: class = " + fxCanvasClass);
 292         Object thisModule = ModuleHelper.getModule(PlatformImpl.class);
 293         Object javafxSwtModule = ModuleHelper.getModule(fxCanvasClass);
 294         for (String pkg : swtNeededPackages) {
 295             System.err.println("add export of " + pkg + " from " + thisModule + " to " + javafxSwtModule);
 296             ModuleHelper.addExports(thisModule, pkg, javafxSwtModule);
 297         }
 298     }
 299 
 300     // FXCanvas-specific initialization
 301     private static void initFXCanvas() {
 302         // Verify that we have the appropriate permission
 303         final SecurityManager sm = System.getSecurityManager();
 304         if (sm != null) {
 305             try {
 306                 sm.checkPermission(FXCANVAS_PERMISSION);
 307             } catch (SecurityException ex) {
 308                 System.err.println("FXCanvas: no permission to access JavaFX internals");
 309                 ex.printStackTrace();
 310                 return;
 311             }
 312         }
 313 
 314         // Find the calling class, ignoring any stack frames from FX application classes
 315         Predicate<StackWalker.StackFrame> classFilter = f ->
 316                 !f.getClassName().startsWith("javafx.application.")
 317                         && !f.getClassName().startsWith("com.sun.javafx.application.");
 318 
 319         final StackWalker walker = AccessController.doPrivileged((PrivilegedAction<StackWalker>) () ->
 320                 StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE));
 321         Optional<StackWalker.StackFrame> frame = walker.walk(
 322                 s -> s.filter(classFilter).findFirst());
 323         System.err.println("frame = " + frame);
 324 
 325         if (frame.isPresent()) {
 326             Class<?> caller = frame.get().getDeclaringClass();
 327             System.err.println("callerClassName = " + caller);
 328 
 329             // Verify that the caller is javafx.embed.swt.FXCanvas
 330             if ("javafx.embed.swt.FXCanvas".equals(caller.getName())) {
 331                 initDeviceDetailsFXCanvas();
 332                 addExportsToFXCanvas(caller);
 333             }
 334         }
 335     }
 336 
 337     private static void installFwEventQueue() {
 338         invokeSwingFXUtilsMethod("installFwEventQueue");
 339     }
 340 
 341     private static void removeFwEventQueue() {
 342         invokeSwingFXUtilsMethod("removeFwEventQueue");
 343     }
 344 
 345     private static void invokeSwingFXUtilsMethod(final String methodName) {
 346         //Use reflection in case we are running compact profile
 347         try {
 348             Class swingFXUtilsClass = Class.forName("javafx.embed.swing.SwingFXUtils");
 349             Method installFwEventQueue = swingFXUtilsClass.getDeclaredMethod(methodName);
 350             AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
 351                 installFwEventQueue.setAccessible(true);
 352                 return null;
 353             });


< prev index next >