< 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

@@ -23,38 +23,42 @@
  * questions.
  */
 
 package com.sun.javafx.application;
 
+import static com.sun.javafx.FXPermissions.CREATE_TRANSPARENT_WINDOW_PERMISSION;
 import com.sun.javafx.PlatformUtil;
 import com.sun.javafx.css.StyleManager;
 import com.sun.javafx.runtime.SystemProperties;
-import static com.sun.javafx.FXPermissions.CREATE_TRANSPARENT_WINDOW_PERMISSION;
+import com.sun.javafx.tk.TKListener;
+import com.sun.javafx.tk.TKStage;
+import com.sun.javafx.tk.Toolkit;
+import com.sun.javafx.util.ModuleHelper;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArraySet;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Predicate;
 
 import javafx.application.Application;
 import javafx.application.ConditionalFeature;
-
-import com.sun.javafx.tk.TKListener;
-import com.sun.javafx.tk.TKStage;
-import com.sun.javafx.tk.Toolkit;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.SimpleBooleanProperty;
 import javafx.scene.Scene;
-
-import java.security.AccessController;
-import java.security.PrivilegedAction;
+import javafx.util.FXPermission;
 
 public class PlatformImpl {
 
     private static AtomicBoolean initialized = new AtomicBoolean(false);
     private static AtomicBoolean platformExit = new AtomicBoolean(false);

@@ -84,12 +88,17 @@
     private static Boolean hasVirtualKeyboard;
     private static Boolean hasTouch;
     private static Boolean hasMultiTouch;
     private static Boolean hasPointer;
     private static boolean isThreadMerged = false;
+    private static String applicationType = "";
     private static BooleanProperty accessibilityActive = new SimpleBooleanProperty();
 
+    // Internal permission used by FXCanvas (SWT interop)
+    private static final FXPermission FXCANVAS_PERMISSION =
+            new FXPermission("accessFXCanvasInternals");
+
     /**
      * Set a flag indicating whether this application should show up in the
      * task bar. The default value is true.
      *
      * @param taskbarApplication the new value of this attribute

@@ -169,10 +178,13 @@
             runLater(r);
             return;
         }
 
         AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+            applicationType = System.getProperty("com.sun.javafx.application.type");
+            if (applicationType == null) applicationType = "";
+
             contextual2DNavigation = Boolean.getBoolean(
                     "com.sun.javafx.isContextual2DNavigation");
             String s = System.getProperty("com.sun.javafx.twoLevelFocus");
             if (s != null) {
                 hasTwoLevelFocus = Boolean.valueOf(s);

@@ -204,10 +216,15 @@
                 isThreadMerged = Boolean.valueOf(s);
             }
             return null;
         });
 
+        System.err.println("PlatformImpl::startup : applicationType = " + applicationType);
+        if ("FXCanvas".equals(applicationType)) {
+            initFXCanvas();
+        }
+
         if (!taskbarApplication) {
             AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
                 System.setProperty("glass.taskbarApplication", "false");
                 return null;
             });

@@ -237,10 +254,88 @@
         if (isThreadMerged) {
             installFwEventQueue();
         }
     }
 
+    // Pass certain system properties to glass via the device details Map
+    private static void initDeviceDetailsFXCanvas() {
+        // Read the javafx.embed.eventProc system property and store
+        // it in an entry in the glass Application device details map
+        final String eventProcProperty = "javafx.embed.eventProc";
+        final long eventProc = AccessController.doPrivileged((PrivilegedAction<Long>) () ->
+                Long.getLong(eventProcProperty, 0));
+        System.err.println("PlatformImpl.initSWT: "
+                + eventProcProperty + " = " + eventProc);
+        if (eventProc != 0L) {
+            // Set the value for the javafx.embed.eventProc
+            // key in the glass Application map
+            Map map = com.sun.glass.ui.Application.getDeviceDetails();
+            if (map == null) {
+                map = new HashMap();
+                com.sun.glass.ui.Application.setDeviceDetails(map);
+            }
+            if (map.get(eventProcProperty) == null) {
+                map.put(eventProcProperty, eventProc);
+            }
+        }
+    }
+
+    // Add the necessary qualified exports to the calling module
+    private static void addExportsToFXCanvas(Class<?> fxCanvasClass) {
+        final String[] swtNeededPackages = {
+            "com.sun.glass.ui",
+            "com.sun.javafx.cursor",
+            "com.sun.javafx.embed",
+            "com.sun.javafx.stage"
+        };
+
+        System.err.println("addExportsToFXCanvas: class = " + fxCanvasClass);
+        Object thisModule = ModuleHelper.getModule(PlatformImpl.class);
+        Object javafxSwtModule = ModuleHelper.getModule(fxCanvasClass);
+        for (String pkg : swtNeededPackages) {
+            System.err.println("add export of " + pkg + " from " + thisModule + " to " + javafxSwtModule);
+            ModuleHelper.addExports(thisModule, pkg, javafxSwtModule);
+        }
+    }
+
+    // FXCanvas-specific initialization
+    private static void initFXCanvas() {
+        // Verify that we have the appropriate permission
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            try {
+                sm.checkPermission(FXCANVAS_PERMISSION);
+            } catch (SecurityException ex) {
+                System.err.println("FXCanvas: no permission to access JavaFX internals");
+                ex.printStackTrace();
+                return;
+            }
+        }
+
+        // Find the calling class, ignoring any stack frames from FX application classes
+        Predicate<StackWalker.StackFrame> classFilter = f ->
+                !f.getClassName().startsWith("javafx.application.")
+                        && !f.getClassName().startsWith("com.sun.javafx.application.");
+
+        final StackWalker walker = AccessController.doPrivileged((PrivilegedAction<StackWalker>) () ->
+                StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE));
+        Optional<StackWalker.StackFrame> frame = walker.walk(
+                s -> s.filter(classFilter).findFirst());
+        System.err.println("frame = " + frame);
+
+        if (frame.isPresent()) {
+            Class<?> caller = frame.get().getDeclaringClass();
+            System.err.println("callerClassName = " + caller);
+
+            // Verify that the caller is javafx.embed.swt.FXCanvas
+            if ("javafx.embed.swt.FXCanvas".equals(caller.getName())) {
+                initDeviceDetailsFXCanvas();
+                addExportsToFXCanvas(caller);
+            }
+        }
+    }
+
     private static void installFwEventQueue() {
         invokeSwingFXUtilsMethod("installFwEventQueue");
     }
 
     private static void removeFwEventQueue() {
< prev index next >