/*
 * Copyright (c) 2010, 2018, 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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.
 */

package com.sun.javafx.tk;

import javafx.application.ConditionalFeature;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.geometry.Dimension2D;
import javafx.scene.Scene;
import javafx.scene.effect.BlurType;
import javafx.scene.image.Image;
import javafx.scene.image.PixelFormat;
import javafx.scene.image.WritableImage;
import javafx.scene.input.Dragboard;
import javafx.scene.input.InputMethodRequests;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.paint.Color;
import javafx.scene.paint.ImagePattern;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Paint;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.PathElement;
import javafx.scene.shape.SVGPath;
import javafx.scene.shape.StrokeLineCap;
import javafx.scene.shape.StrokeLineJoin;
import javafx.scene.shape.StrokeType;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.Window;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import com.sun.glass.ui.CommonDialogs.FileChooserResult;
import com.sun.glass.ui.GlassRobot;
import com.sun.glass.utils.NativeLibLoader;
import com.sun.javafx.PlatformUtil;
import com.sun.javafx.beans.event.AbstractNotifyListener;
import com.sun.javafx.embed.HostInterface;
import com.sun.javafx.geom.Path2D;
import com.sun.javafx.geom.transform.BaseTransform;
import com.sun.javafx.perf.PerformanceTracker;
import com.sun.javafx.runtime.VersionInfo;
import com.sun.javafx.runtime.async.AsyncOperation;
import com.sun.javafx.runtime.async.AsyncOperationListener;
import com.sun.javafx.scene.SceneHelper;
import com.sun.javafx.scene.text.TextLayoutFactory;
import com.sun.javafx.sg.prism.NGCamera;
import com.sun.javafx.sg.prism.NGLightBase;
import com.sun.javafx.sg.prism.NGNode;
import com.sun.javafx.util.Utils;
import com.sun.scenario.DelayedRunnable;
import com.sun.scenario.animation.AbstractMasterTimer;
import com.sun.scenario.effect.AbstractShadow.ShadowMode;
import com.sun.scenario.effect.Color4f;
import com.sun.scenario.effect.FilterContext;
import com.sun.scenario.effect.Filterable;


public abstract class Toolkit {
    private static String tk;
    private static Toolkit TOOLKIT;
    private static Thread fxUserThread = null;

    private static final String QUANTUM_TOOLKIT     = "com.sun.javafx.tk.quantum.QuantumToolkit";
    private static final String DEFAULT_TOOLKIT     = QUANTUM_TOOLKIT;

    private static final Map gradientMap = new WeakHashMap();

    private static final boolean verbose = AccessController.doPrivileged((PrivilegedAction<Boolean>) () -> Boolean.getBoolean("javafx.verbose"));

    private static final String[] msLibNames = {
        "api-ms-win-core-console-l1-1-0",
        "api-ms-win-core-datetime-l1-1-0",
        "api-ms-win-core-debug-l1-1-0",
        "api-ms-win-core-errorhandling-l1-1-0",
        "api-ms-win-core-file-l1-1-0",
        "api-ms-win-core-file-l1-2-0",
        "api-ms-win-core-file-l2-1-0",
        "api-ms-win-core-handle-l1-1-0",
        "api-ms-win-core-heap-l1-1-0",
        "api-ms-win-core-interlocked-l1-1-0",
        "api-ms-win-core-libraryloader-l1-1-0",
        "api-ms-win-core-localization-l1-2-0",
        "api-ms-win-core-memory-l1-1-0",
        "api-ms-win-core-namedpipe-l1-1-0",
        "api-ms-win-core-processenvironment-l1-1-0",
        "api-ms-win-core-processthreads-l1-1-0",
        "api-ms-win-core-processthreads-l1-1-1",
        "api-ms-win-core-profile-l1-1-0",
        "api-ms-win-core-rtlsupport-l1-1-0",
        "api-ms-win-core-string-l1-1-0",
        "api-ms-win-core-synch-l1-1-0",
        "api-ms-win-core-synch-l1-2-0",
        "api-ms-win-core-sysinfo-l1-1-0",
        "api-ms-win-core-timezone-l1-1-0",
        "api-ms-win-core-util-l1-1-0",
        "api-ms-win-crt-conio-l1-1-0",
        "api-ms-win-crt-convert-l1-1-0",
        "api-ms-win-crt-environment-l1-1-0",
        "api-ms-win-crt-filesystem-l1-1-0",
        "api-ms-win-crt-heap-l1-1-0",
        "api-ms-win-crt-locale-l1-1-0",
        "api-ms-win-crt-math-l1-1-0",
        "api-ms-win-crt-multibyte-l1-1-0",
        "api-ms-win-crt-private-l1-1-0",
        "api-ms-win-crt-process-l1-1-0",
        "api-ms-win-crt-runtime-l1-1-0",
        "api-ms-win-crt-stdio-l1-1-0",
        "api-ms-win-crt-string-l1-1-0",
        "api-ms-win-crt-time-l1-1-0",
        "api-ms-win-crt-utility-l1-1-0",
        "ucrtbase",

        // Finally load VS 2017 DLLs in the following order
        "vcruntime140",
        "msvcp140",
        "concrt140"
};

    private static String lookupToolkitClass(String name) {
        if ("prism".equalsIgnoreCase(name)) {
            return QUANTUM_TOOLKIT;
        } else if ("quantum".equalsIgnoreCase(name)) {
            return QUANTUM_TOOLKIT;
        }
        return name;
    }

    public static synchronized void loadMSWindowsLibraries() {
        for (String libName : msLibNames) {
            try {
                NativeLibLoader.loadLibrary(libName);
            } catch (Throwable t) {
                if (verbose) {
                    System.err.println("Error: failed to load "
                            + libName + ".dll : " + t);
                }
            }
        }
    }

    private static String getDefaultToolkit() {
        if (PlatformUtil.isWindows()) {
            return DEFAULT_TOOLKIT;
        } else if (PlatformUtil.isMac()) {
            return DEFAULT_TOOLKIT;
        } else if (PlatformUtil.isLinux()) {
            return DEFAULT_TOOLKIT;
        } else if (PlatformUtil.isIOS()) {
            return DEFAULT_TOOLKIT;
        } else if (PlatformUtil.isAndroid()) {
           return DEFAULT_TOOLKIT;
        }

        throw new UnsupportedOperationException(System.getProperty("os.name") + " is not supported");
    }

    public static synchronized Toolkit getToolkit() {
        if (TOOLKIT != null) {
            return TOOLKIT;
        }

        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            // Get the javafx.version and javafx.runtime.version from a preconstructed
            // java class, VersionInfo, created at build time.
            VersionInfo.setupSystemProperties();
            return null;
        });

        // This loading of msvcp140.dll and vcruntime140.dll (VS2017) is required on Windows platforms
        if (PlatformUtil.isWindows()) {
            loadMSWindowsLibraries();
        }

        boolean userSpecifiedToolkit = true;

        // Check a system property to see if there is a specific toolkit to use.
        // This is not a doPriviledged check so that applets cannot use this.
        String forcedToolkit = null;
        try {
            forcedToolkit = System.getProperty("javafx.toolkit");
        } catch (SecurityException ex) {}

        if (forcedToolkit == null) {
            forcedToolkit = tk;
        }
        if (forcedToolkit == null) {
            userSpecifiedToolkit = false;
            forcedToolkit = getDefaultToolkit();
        }

        if (forcedToolkit.indexOf('.') == -1) {
            // Turn a short name into a fully qualified classname
            forcedToolkit = lookupToolkitClass(forcedToolkit);
        }

        boolean printToolkit = verbose
                || (userSpecifiedToolkit && !forcedToolkit.endsWith("StubToolkit"));

        try {
            Class clz = null;

            try {
                // try our priveledged loader first
                final ClassLoader loader = Toolkit.class.getClassLoader();
                clz = Class.forName(forcedToolkit, false, loader);
            } catch (ClassNotFoundException e) {
                // fall back and try the application class loader
                final ClassLoader loader = Thread.currentThread().getContextClassLoader();
                clz = Class.forName(forcedToolkit, false, loader);
            }

            // Check that clz is a subclass of Toolkit
            if (!Toolkit.class.isAssignableFrom(clz)) {
                throw new IllegalArgumentException("Unrecognized FX Toolkit class: "
                        + forcedToolkit);
            }

            TOOLKIT = (Toolkit)clz.newInstance();
            if (TOOLKIT.init()) {
                if (printToolkit) {
                    System.err.println("JavaFX: using " + forcedToolkit);
                }
                return TOOLKIT;
            }
            TOOLKIT = null;
        } catch (Exception any) {
            TOOLKIT = null;
            any.printStackTrace();
        }

        throw new RuntimeException("No toolkit found");
    }

    protected static Thread getFxUserThread() {
        return fxUserThread;
    }

    protected static void setFxUserThread(Thread t) {
        if (fxUserThread != null) {
            throw new IllegalStateException("Error: FX User Thread already initialized");
        }

        fxUserThread = t;
    }

    public void checkFxUserThread() {
        // Throw exception if not on FX user thread
        if (!isFxUserThread()) {
            throw new IllegalStateException("Not on FX application thread; currentThread = "
                    + Thread.currentThread().getName());
        }
    }

    // Toolkit can override this if needed
    public boolean isFxUserThread() {
        return Thread.currentThread() == fxUserThread;
    }

    protected Toolkit() {
    }

    public abstract boolean init();

    
Indicates whether or not a nested event loop can be started from the current thread in the current state. Note that a nested event loop is not allowed outside of an event handler.
Returns:flag indicating whether a nested event loop can be started.
/** * Indicates whether or not a nested event loop can be started * from the current thread in the current state. Note that a nested * event loop is not allowed outside of an event handler. * * @return flag indicating whether a nested event loop can be started. */
public abstract boolean canStartNestedEventLoop();
Enter a nested event loop and block until the corresponding exitNestedEventLoop call is made. The key passed into this method is used to uniquely identify the matched enter/exit pair. This method creates a new nested event loop and blocks until the corresponding exitNestedEventLoop method is called with the same key. The return value of this method will be the rval object supplied to the exitNestedEventLoop method call that unblocks it.
Params:
  • key – the Object that identifies the nested event loop, which must not be null
Throws:
Returns:the value passed into the corresponding call to exitEventLoop
/** * Enter a nested event loop and block until the corresponding * exitNestedEventLoop call is made. * The key passed into this method is used to * uniquely identify the matched enter/exit pair. This method creates a * new nested event loop and blocks until the corresponding * exitNestedEventLoop method is called with the same key. * The return value of this method will be the {@code rval} * object supplied to the exitNestedEventLoop method call that unblocks it. * * @param key the Object that identifies the nested event loop, which * must not be null * * @throws IllegalArgumentException if the specified key is associated * with a nested event loop that has not yet returned * * @throws NullPointerException if the key is null * * @throws IllegalStateException if this method is called on a thread * other than the FX Application thread * * @return the value passed into the corresponding call to exitEventLoop */
public abstract Object enterNestedEventLoop(Object key);
Exit a nested event loop and unblock the caller of the corresponding enterNestedEventLoop. The key passed into this method is used to uniquely identify the matched enter/exit pair. This method causes the nested event loop that was previously created with the key to exit and return control to the caller. If the specified nested event loop is not the inner-most loop then it will not return until all other inner loops also exit.
Params:
  • key – the Object that identifies the nested event loop, which must not be null
  • rval – an Object that is returned to the caller of the corresponding enterNestedEventLoop. This may be null.
Throws:
/** * Exit a nested event loop and unblock the caller of the * corresponding enterNestedEventLoop. * The key passed into this method is used to * uniquely identify the matched enter/exit pair. This method causes the * nested event loop that was previously created with the key to exit and * return control to the caller. If the specified nested event loop is not * the inner-most loop then it will not return until all other inner loops * also exit. * * @param key the Object that identifies the nested event loop, which * must not be null * * @param rval an Object that is returned to the caller of the * corresponding enterNestedEventLoop. This may be null. * * @throws IllegalArgumentException if the specified key is not associated * with an active nested event loop * * @throws NullPointerException if the key is null * * @throws IllegalStateException if this method is called on a thread * other than the FX Application thread */
public abstract void exitNestedEventLoop(Object key, Object rval); public abstract void exitAllNestedEventLoops(); public abstract boolean isNestedLoopRunning(); public abstract TKStage createTKStage(Window peerWindow, boolean securityDialog, StageStyle stageStyle, boolean primary, Modality modality, TKStage owner, boolean rtl, AccessControlContext acc); public abstract TKStage createTKPopupStage(Window peerWindow, StageStyle popupStyle, TKStage owner, AccessControlContext acc); public abstract TKStage createTKEmbeddedStage(HostInterface host, AccessControlContext acc);
Creates an AppletWindow using the provided window pointer as the parent window.
Params:
  • parent – the native parent which will contain the primary stage window(s). Used on Windows/Linux platforms.
  • serverName – the name of CARemoteLayerServer which will be used to register native layer. Used on Mac platform.
/** * Creates an AppletWindow using the provided window pointer as the parent * window. * * @param parent the native parent which will contain the primary stage * window(s). Used on Windows/Linux platforms. * * @param serverName the name of CARemoteLayerServer which * will be used to register native layer. Used on Mac platform. */
public abstract AppletWindow createAppletWindow(long parent, String serverName);
Perform cleanup in preparation for applet termination, including closing the applet window.
/** * Perform cleanup in preparation for applet termination, including closing * the applet window. */
public abstract void closeAppletWindow(); private final Map<TKPulseListener,AccessControlContext> stagePulseListeners = new WeakHashMap<TKPulseListener,AccessControlContext>(); private final Map<TKPulseListener,AccessControlContext> scenePulseListeners = new WeakHashMap<TKPulseListener,AccessControlContext>(); private final Map<TKPulseListener,AccessControlContext> postScenePulseListeners = new WeakHashMap<TKPulseListener,AccessControlContext>(); private final Map<TKListener,AccessControlContext> toolkitListeners = new WeakHashMap<TKListener,AccessControlContext>(); // The set of shutdown hooks is strongly held to avoid premature GC. private final Set<Runnable> shutdownHooks = new HashSet<Runnable>(); private void runPulse(final TKPulseListener listener, final AccessControlContext acc) { if (acc == null) { throw new IllegalStateException("Invalid AccessControlContext"); } AccessController.doPrivileged((PrivilegedAction<Void>) () -> { listener.pulse(); return null; }, acc); } public void firePulse() { // Stages need to be notified of pulses before scenes so the Stage can resized // and those changes propogated to scene before it gets its pulse to update // Copy of listener map final Map<TKPulseListener,AccessControlContext> stagePulseList = new WeakHashMap<TKPulseListener,AccessControlContext>(); final Map<TKPulseListener,AccessControlContext> scenePulseList = new WeakHashMap<TKPulseListener,AccessControlContext>(); final Map<TKPulseListener,AccessControlContext> postScenePulseList = new WeakHashMap<TKPulseListener,AccessControlContext>(); synchronized (this) { stagePulseList.putAll(stagePulseListeners); scenePulseList.putAll(scenePulseListeners); postScenePulseList.putAll(postScenePulseListeners); } for (Map.Entry<TKPulseListener,AccessControlContext> entry : stagePulseList.entrySet()) { runPulse(entry.getKey(), entry.getValue()); } for (Map.Entry<TKPulseListener,AccessControlContext> entry : scenePulseList.entrySet()) { runPulse(entry.getKey(), entry.getValue()); } for (Map.Entry<TKPulseListener,AccessControlContext> entry : postScenePulseList.entrySet()) { runPulse(entry.getKey(), entry.getValue()); } if (lastTkPulseListener != null) { runPulse(lastTkPulseListener, lastTkPulseAcc); } } public void addStageTkPulseListener(TKPulseListener listener) { if (listener == null) { return; } synchronized (this) { AccessControlContext acc = AccessController.getContext(); stagePulseListeners.put(listener, acc); } } public void removeStageTkPulseListener(TKPulseListener listener) { synchronized (this) { stagePulseListeners.remove(listener); } } public void addSceneTkPulseListener(TKPulseListener listener) { if (listener == null) { return; } synchronized (this) { AccessControlContext acc = AccessController.getContext(); scenePulseListeners.put(listener, acc); } } public void removeSceneTkPulseListener(TKPulseListener listener) { synchronized (this) { scenePulseListeners.remove(listener); } } public void addPostSceneTkPulseListener(TKPulseListener listener) { if (listener == null) { return; } synchronized (this) { AccessControlContext acc = AccessController.getContext(); postScenePulseListeners.put(listener, acc); } } public void removePostSceneTkPulseListener(TKPulseListener listener) { synchronized (this) { postScenePulseListeners.remove(listener); } } public void addTkListener(TKListener listener) { if (listener == null) { return; } AccessControlContext acc = AccessController.getContext(); toolkitListeners.put(listener, acc); } public void removeTkListener(TKListener listener) { toolkitListeners.remove(listener); } private TKPulseListener lastTkPulseListener = null; private AccessControlContext lastTkPulseAcc = null; public void setLastTkPulseListener(TKPulseListener listener) { lastTkPulseAcc = AccessController.getContext(); lastTkPulseListener = listener; } public void addShutdownHook(Runnable hook) { if (hook == null) { return; } synchronized (shutdownHooks) { shutdownHooks.add(hook); } } public void removeShutdownHook(Runnable hook) { synchronized (shutdownHooks) { shutdownHooks.remove(hook); } } protected void notifyShutdownHooks() { List<Runnable> hooks; synchronized (shutdownHooks) { hooks = new ArrayList<Runnable>(shutdownHooks); shutdownHooks.clear(); } for (Runnable hook : hooks) { hook.run(); } } public void notifyWindowListeners(final List<TKStage> windows) { for (Map.Entry<TKListener,AccessControlContext> entry : toolkitListeners.entrySet()) { final TKListener listener = entry.getKey(); final AccessControlContext acc = entry.getValue(); if (acc == null) { throw new IllegalStateException("Invalid AccessControlContext"); } AccessController.doPrivileged((PrivilegedAction<Void>) () -> { listener.changedTopLevelWindows(windows); return null; }, acc); } } public void notifyLastNestedLoopExited() { for (TKListener listener: toolkitListeners.keySet()) { listener.exitedLastNestedLoop(); } } // notify the pulse timer code that we need the next pulse to happen // this flag is cleared each cycle so subsequent pulses must be requested public abstract void requestNextPulse(); public abstract Future addRenderJob(RenderJob rj); public abstract ImageLoader loadImage(String url, double width, double height, boolean preserveRatio, boolean smooth); public abstract ImageLoader loadImage(InputStream stream, double width, double height, boolean preserveRatio, boolean smooth); public abstract AsyncOperation loadImageAsync( AsyncOperationListener<? extends ImageLoader> listener, String url, double width, double height, boolean preserveRatio, boolean smooth); /* * The loadPlatformImage method supports the following image types: * - an object returned by the renderToImage method * - an instance of com.sun.prism.Image (in case of prism) * - an instance of an external image object, which can be a BufferedImage * If JavaFX Image had one more constructor Image(ImageLoader), * we could introduce a different method for external image loading support. */ public abstract ImageLoader loadPlatformImage(Object platformImage); public abstract PlatformImage createPlatformImage(int w, int h); // Indicates the default state of smooth for ImageView and MediaView // Subclasses may override this to provide a platform-specific default public boolean getDefaultImageSmooth() { return true; } public abstract void startup(Runnable runnable); public abstract void defer(Runnable runnable); public void exit() { fxUserThread = null; } public abstract Map<Object, Object> getContextMap(); public abstract int getRefreshRate(); public abstract void setAnimationRunnable(DelayedRunnable animationRunnable); public abstract PerformanceTracker getPerformanceTracker(); public abstract PerformanceTracker createPerformanceTracker(); //to be used for testing only public abstract void waitFor(Task t); private Object checkSingleColor(List<Stop> stops) { if (stops.size() == 2) { Color c = stops.get(0).getColor(); if (c.equals(stops.get(1).getColor())) { return Toolkit.getPaintAccessor().getPlatformPaint(c); } } return null; } private Object getPaint(LinearGradient paint) { Object p = gradientMap.get(paint); if (p != null) { return p; } p = checkSingleColor(paint.getStops()); if (p == null) { p = createLinearGradientPaint(paint); } gradientMap.put(paint, p); return p; } private Object getPaint(RadialGradient paint) { Object p = gradientMap.get(paint); if (p != null) { return p; } p = checkSingleColor(paint.getStops()); if (p == null) { p = createRadialGradientPaint(paint); } gradientMap.put(paint, p); return p; } public Object getPaint(Paint paint) { if (paint instanceof Color) { return createColorPaint((Color) paint); } if (paint instanceof LinearGradient) { return getPaint((LinearGradient) paint); } if (paint instanceof RadialGradient) { return getPaint((RadialGradient) paint); } if (paint instanceof ImagePattern) { return createImagePatternPaint((ImagePattern) paint); } return null; } protected static final double clampStopOffset(double offset) { return (offset > 1.0) ? 1.0 : (offset < 0.0) ? 0.0 : offset; } protected abstract Object createColorPaint(Color paint); protected abstract Object createLinearGradientPaint(LinearGradient paint); protected abstract Object createRadialGradientPaint(RadialGradient paint); protected abstract Object createImagePatternPaint(ImagePattern paint); public abstract void accumulateStrokeBounds(com.sun.javafx.geom.Shape shape, float bbox[], StrokeType type, double strokewidth, StrokeLineCap cap, StrokeLineJoin join, float miterLimit, BaseTransform tx); public abstract boolean strokeContains(com.sun.javafx.geom.Shape shape, double x, double y, StrokeType type, double strokewidth, StrokeLineCap cap, StrokeLineJoin join, float miterLimit); public abstract com.sun.javafx.geom.Shape createStrokedShape(com.sun.javafx.geom.Shape shape, StrokeType type, double strokewidth, StrokeLineCap cap, StrokeLineJoin join, float miterLimit, float[] dashArray, float dashOffset); public abstract int getKeyCodeForChar(String character); public abstract Dimension2D getBestCursorSize(int preferredWidth, int preferredHeight); public abstract int getMaximumCursorColors(); public abstract PathElement[] convertShapeToFXPath(Object shape); public abstract Filterable toFilterable(Image img); public abstract FilterContext getFilterContext(Object config); public abstract boolean isForwardTraversalKey(KeyEvent e); public abstract boolean isBackwardTraversalKey(KeyEvent e); public abstract AbstractMasterTimer getMasterTimer(); public abstract FontLoader getFontLoader(); public abstract TextLayoutFactory getTextLayoutFactory(); public abstract Object createSVGPathObject(SVGPath svgpath); public abstract Path2D createSVGPath2D(SVGPath svgpath);
Tests whether the pixel on the given coordinates in the given image is non-empty (not fully transparent). Return value is not defined for pixels out of the image bounds.
/** * Tests whether the pixel on the given coordinates in the given image * is non-empty (not fully transparent). Return value is not defined * for pixels out of the image bounds. */
public abstract boolean imageContains(Object image, float x, float y); public abstract TKClipboard getSystemClipboard(); public TKClipboard createLocalClipboard() { return new LocalClipboard(); } public abstract TKSystemMenu getSystemMenu(); public abstract TKClipboard getNamedClipboard(String name); public boolean isSupported(ConditionalFeature feature) { return false; } public boolean isMSAASupported() { return false; } public abstract ScreenConfigurationAccessor setScreenConfigurationListener(TKScreenConfigurationListener listener); public abstract Object getPrimaryScreen(); public abstract List<?> getScreens(); public abstract ScreenConfigurationAccessor getScreenConfigurationAccessor(); public abstract void registerDragGestureListener(TKScene s, Set<TransferMode> tm, TKDragGestureListener l);
This function is called when a drag originates within a JavaFX application. This means that drags that originate in other applications / from the OS do not call this function. The argument o represents an object used to identify a scene on which the drag has started.
/** * This function is called when a drag originates within a JavaFX application. * This means that drags that originate in other applications / from the OS * do not call this function. * The argument o represents an object used to identify a scene on which * the drag has started. */
public abstract void startDrag(TKScene scene, Set<TransferMode> tm, TKDragSourceListener l, Dragboard dragboard); // template function which can be implemented by toolkit impls such that they // can be informed when a drag and drop operation has completed. This allows // for any cleanup that may need to be done. public void stopDrag(Dragboard dragboard) { // no-op } public abstract void enableDrop(TKScene s, TKDropTargetListener l); public interface Task { boolean isFinished(); } public Color4f toColor4f(Color color) { return new Color4f((float)color.getRed(), (float)color.getGreen(), (float)color.getBlue(), (float)color.getOpacity()); } public ShadowMode toShadowMode(BlurType blurType) { switch (blurType) { case ONE_PASS_BOX: return ShadowMode.ONE_PASS_BOX; case TWO_PASS_BOX: return ShadowMode.TWO_PASS_BOX; case THREE_PASS_BOX: return ShadowMode.THREE_PASS_BOX; default: return ShadowMode.GAUSSIAN; } } public abstract void installInputMethodRequests(TKScene scene, InputMethodRequests requests); /* * ImageRenderingContext holds the many parameters passed to * the renderToImage method. * The use of the parameters is specified by the renderToImage * method. * @see #renderToImage */ public static class ImageRenderingContext { // Node to be rendered public NGNode root; // Viewport for rendering public int x; public int y; public int width; public int height; // Initial transform for root node public BaseTransform transform; // Rendering parameters either from Scene or SnapShotParams public boolean depthBuffer; public Object platformPaint; public NGCamera camera; public NGLightBase[] lights; // PlatformImage into which to render or null public Object platformImage; } /* * This method renders a PG-graph to a platform image object. * The returned object can be turned into a useable * scene graph image using the appropriate factor of the * Image class. * The scale specified in the params is used to scale the * entire rendering before any transforms in the nodes are * applied. * The width and height specified in the params represent * the user space dimensions to be rendered. The returned * image will be large enough to hold these dimensions * scaled by the scale parameter. * The depthBuffer specified in the params is used to determine * with or without depthBuffer rendering should be performed. * The root node is the root of a tree of toolkit-specific * scene graph peer nodes to be rendered and should have * been previously created by this toolkit. * The platformPaint specified in the params must be * generated by the appropriate Toolkit.createPaint method * and is used to fill the background of the image before * rendering the scene graph. * The platformImage specified in the params may be non-null * and should be a previous return value from this method. * If it is non-null then it may be reused as the return value * of this method if it is still valid and large enough to * hold the requested size. * * @param context a ImageRenderingContext instance specifying * the various rendering parameters * @return a platform specific image object * @see Toolkit.getImageAccessor().fromPlatformImage */ public abstract Object renderToImage(ImageRenderingContext context);
Returns the key code for the key which is commonly used on the corresponding platform as a modifier key in shortcuts. For example it is KeyCode.CONTROL on Windows (Ctrl + C, Ctrl + V ...) and KeyCode.META on MacOS (Cmd + C, Cmd + V ...).
Returns:the key code for shortcut modifier key
/** * Returns the key code for the key which is commonly used on the * corresponding platform as a modifier key in shortcuts. For example * it is {@code KeyCode.CONTROL} on Windows (Ctrl + C, Ctrl + V ...) and * {@code KeyCode.META} on MacOS (Cmd + C, Cmd + V ...). * * @return the key code for shortcut modifier key */
public KeyCode getPlatformShortcutKey() { return PlatformUtil.isMac() ? KeyCode.META : KeyCode.CONTROL; } public abstract FileChooserResult showFileChooser( TKStage ownerWindow, String title, File initialDirectory, String initialFileName, FileChooserType fileChooserType, List<ExtensionFilter> extensionFilters, ExtensionFilter selectedFilter); public abstract File showDirectoryChooser( TKStage ownerWindow, String title, File initialDirectory); /* * Methods for obtaining "double-click" speed value. */ public abstract long getMultiClickTime(); public abstract int getMultiClickMaxX(); public abstract int getMultiClickMaxY(); private CountDownLatch pauseScenesLatch = null; public interface WritableImageAccessor { public void loadTkImage(WritableImage wimg, Object loader); public Object getTkImageLoader(WritableImage wimg); } private static WritableImageAccessor writableImageAccessor = null; public static void setWritableImageAccessor(WritableImageAccessor accessor) { writableImageAccessor = accessor; } public static WritableImageAccessor getWritableImageAccessor() { return writableImageAccessor; } public interface PaintAccessor { public boolean isMutable(Paint paint); public Object getPlatformPaint(Paint paint); public void addListener(Paint paint, AbstractNotifyListener platformChangeListener); public void removeListener(Paint paint, AbstractNotifyListener platformChangeListener); } private static PaintAccessor paintAccessor = null; public static void setPaintAccessor(PaintAccessor accessor) { paintAccessor = accessor; } public static PaintAccessor getPaintAccessor() { return paintAccessor; } public interface ImageAccessor { public boolean isAnimation(Image image); public ReadOnlyObjectProperty<PlatformImage>getImageProperty(Image image); public int[] getPreColors(PixelFormat<ByteBuffer> pf); public int[] getNonPreColors(PixelFormat<ByteBuffer> pf); public Object getPlatformImage(Image image); public Image fromPlatformImage(Object image); } private static ImageAccessor imageAccessor; static { // Need to ensure that the Image class is loaded since Toolkit class // is the provider of getImageAccessor method and sets the accessor. Utils.forceInit(Image.class); } public static void setImageAccessor(ImageAccessor accessor) { imageAccessor = accessor; } public static ImageAccessor getImageAccessor() { return imageAccessor; } public String getThemeName() { return null; } public abstract GlassRobot createRobot(); }