Bläddra i källkod

Changing formatting to be google format style for the JME standard.

KEVIN-DESKTOP\kevinba 2 år sedan
förälder
incheckning
6a590dbc99

+ 12 - 14
jme3-android/src/main/java/com/jme3/system/android/OGLESContext.java

@@ -556,17 +556,15 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
         return result;
     }
 
-	@Override
-	public Monitors getMonitors()
-	{
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public int getPrimaryMonitor()
-	{
-		// TODO Auto-generated method stub
-		return 0;
-	}
-}
+    @Override
+    public Monitors getMonitors() {
+      // TODO Auto-generated method stub
+      return null;
+    }
+
+    @Override
+    public int getPrimaryMonitor() {
+      // TODO Auto-generated method stub
+      return 0;
+    }
+  }

+ 785 - 823
jme3-core/src/main/java/com/jme3/app/LegacyApplication.java

@@ -1,33 +1,27 @@
 /*
- * Copyright (c) 2009-2022 jMonkeyEngine
- * All rights reserved.
+ * Copyright (c) 2009-2022 jMonkeyEngine All rights reserved.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * Redistribution and use in source and binary forms, with or without modification, are permitted
+ * provided that the following conditions are met:
  *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions
+ * and the following disclaimer.
  *
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials provided with
+ * the distribution.
  *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors may be used to endorse or
+ * promote products derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 package com.jme3.app;
 
@@ -56,824 +50,792 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 /**
- * The <code>LegacyApplication</code> class represents an instance of a
- * real-time 3D rendering jME application.
+ * The <code>LegacyApplication</code> class represents an instance of a real-time 3D rendering jME
+ * application.
  *
  * An <code>LegacyApplication</code> provides all the tools that are commonly used in jME3
  * applications.
  *
- * jME3 applications *SHOULD NOT EXTEND* this class but extend {@link com.jme3.app.SimpleApplication} instead.
+ * jME3 applications *SHOULD NOT EXTEND* this class but extend
+ * {@link com.jme3.app.SimpleApplication} instead.
  *
  */
 public class LegacyApplication implements Application, SystemListener {
 
-    private static final Logger logger = Logger.getLogger(LegacyApplication.class.getName());
-
-    protected AssetManager assetManager;
-
-    protected AudioRenderer audioRenderer;
-    protected Renderer renderer;
-    protected RenderManager renderManager;
-    protected ViewPort viewPort;
-    protected ViewPort guiViewPort;
-
-    protected JmeContext context;
-    protected AppSettings settings;
-    protected Timer timer = new NanoTimer();
-    protected Camera cam;
-    protected Listener listener;
-
-    protected boolean inputEnabled = true;
-    protected LostFocusBehavior lostFocusBehavior = LostFocusBehavior.ThrottleOnLostFocus;
-    protected float speed = 1f;
-    protected boolean paused = false;
-    protected MouseInput mouseInput;
-    protected KeyInput keyInput;
-    protected JoyInput joyInput;
-    protected TouchInput touchInput;
-    protected InputManager inputManager;
-    protected AppStateManager stateManager;
-
-    protected AppProfiler prof;
-
-    private final ConcurrentLinkedQueue<AppTask<?>> taskQueue = new ConcurrentLinkedQueue<>();
-
-    /**
-     * Create a new instance of <code>LegacyApplication</code>.
-     */
-    public LegacyApplication() {
-        this((AppState[]) null);
-    }
-
-    /**
-     * Create a new instance of <code>LegacyApplication</code>, preinitialized
-     * with the specified set of app states.
-     *
-     * @param initialStates app states to pre-attach, or null for none
-     */
-    public LegacyApplication(AppState... initialStates) {
-        initStateManager();
-
-        if (initialStates != null) {
-            for (AppState a : initialStates) {
-                if (a != null) {
-                    stateManager.attach(a);
-                }
-            }
-        }
-    }
-
-    /**
-     * Determine the application's behavior when unfocused.
-     *
-     * @return The lost focus behavior of the application.
-     */
-    @Override
-    public LostFocusBehavior getLostFocusBehavior() {
-        return lostFocusBehavior;
-    }
-
-    /**
-     * Changes the application's behavior when unfocused.
-     *
-     * By default, the application will
-     * {@link LostFocusBehavior#ThrottleOnLostFocus throttle the update loop}
-     * so as not to use 100% of the CPU when out of focus, e.g.
-     * alt-tabbed, minimized, or hidden by another window.
-     *
-     * @param lostFocusBehavior The new lost focus behavior to use.
-     *
-     * @see LostFocusBehavior
-     */
-    @Override
-    public void setLostFocusBehavior(LostFocusBehavior lostFocusBehavior) {
-        this.lostFocusBehavior = lostFocusBehavior;
-    }
-
-    /**
-     * Returns true if pause on lost focus is enabled, false otherwise.
-     *
-     * @return true if pause on lost focus is enabled
-     *
-     * @see #getLostFocusBehavior()
-     */
-    @Override
-    public boolean isPauseOnLostFocus() {
-        return getLostFocusBehavior() == LostFocusBehavior.PauseOnLostFocus;
-    }
-
-    /**
-     * Enable or disable pause on lost focus.
-     * <p>
-     * By default, pause on lost focus is enabled.
-     * If enabled, the application will stop updating
-     * when it loses focus or becomes inactive (e.g. alt-tab).
-     * For online or real-time applications, this might be undesirable,
-     * so this feature should be disabled. For other applications,
-     * it is best to keep it enabled so the CPU is not used unnecessarily.
-     *
-     * @param pauseOnLostFocus True to enable pause on lost focus, false
-     * otherwise.
-     *
-     * @see #setLostFocusBehavior(com.jme3.app.LostFocusBehavior)
-     */
-    @Override
-    public void setPauseOnLostFocus(boolean pauseOnLostFocus) {
-        if (pauseOnLostFocus) {
-            setLostFocusBehavior(LostFocusBehavior.PauseOnLostFocus);
-        } else {
-            setLostFocusBehavior(LostFocusBehavior.Disabled);
+  private static final Logger logger = Logger.getLogger(LegacyApplication.class.getName());
+
+  protected AssetManager assetManager;
+
+  protected AudioRenderer audioRenderer;
+  protected Renderer renderer;
+  protected RenderManager renderManager;
+  protected ViewPort viewPort;
+  protected ViewPort guiViewPort;
+
+  protected JmeContext context;
+  protected AppSettings settings;
+  protected Timer timer = new NanoTimer();
+  protected Camera cam;
+  protected Listener listener;
+
+  protected boolean inputEnabled = true;
+  protected LostFocusBehavior lostFocusBehavior = LostFocusBehavior.ThrottleOnLostFocus;
+  protected float speed = 1f;
+  protected boolean paused = false;
+  protected MouseInput mouseInput;
+  protected KeyInput keyInput;
+  protected JoyInput joyInput;
+  protected TouchInput touchInput;
+  protected InputManager inputManager;
+  protected AppStateManager stateManager;
+
+  protected AppProfiler prof;
+
+  private final ConcurrentLinkedQueue<AppTask<?>> taskQueue = new ConcurrentLinkedQueue<>();
+
+  /**
+   * Create a new instance of <code>LegacyApplication</code>.
+   */
+  public LegacyApplication() {
+    this((AppState[]) null);
+  }
+
+  /**
+   * Create a new instance of <code>LegacyApplication</code>, preinitialized with the specified set
+   * of app states.
+   *
+   * @param initialStates app states to pre-attach, or null for none
+   */
+  public LegacyApplication(AppState... initialStates) {
+    initStateManager();
+
+    if (initialStates != null) {
+      for (AppState a : initialStates) {
+        if (a != null) {
+          stateManager.attach(a);
         }
-    }
-
-    @Deprecated
-    public void setAssetManager(AssetManager assetManager) {
-        if (this.assetManager != null)
-            throw new IllegalStateException("Can only set asset manager"
-                    + " before initialization.");
-
-        this.assetManager = assetManager;
-    }
-
-    private void initAssetManager() {
-        URL assetCfgUrl = null;
-
-        if (settings != null) {
-            String assetCfg = settings.getString("AssetConfigURL");
-            if (assetCfg != null) {
-                try {
-                    assetCfgUrl = new URL(assetCfg);
-                } catch (MalformedURLException ex) {
-                }
-                if (assetCfgUrl == null) {
-                    assetCfgUrl = LegacyApplication.class.getClassLoader().getResource(assetCfg);
-                    if (assetCfgUrl == null) {
-                        logger.log(Level.SEVERE, "Unable to access AssetConfigURL in asset config:{0}", assetCfg);
-                        return;
-                    }
-                }
-            }
+      }
+    }
+  }
+
+  /**
+   * Determine the application's behavior when unfocused.
+   *
+   * @return The lost focus behavior of the application.
+   */
+  @Override
+  public LostFocusBehavior getLostFocusBehavior() {
+    return lostFocusBehavior;
+  }
+
+  /**
+   * Changes the application's behavior when unfocused.
+   *
+   * By default, the application will {@link LostFocusBehavior#ThrottleOnLostFocus throttle the
+   * update loop} so as not to use 100% of the CPU when out of focus, e.g. alt-tabbed, minimized, or
+   * hidden by another window.
+   *
+   * @param lostFocusBehavior The new lost focus behavior to use.
+   *
+   * @see LostFocusBehavior
+   */
+  @Override
+  public void setLostFocusBehavior(LostFocusBehavior lostFocusBehavior) {
+    this.lostFocusBehavior = lostFocusBehavior;
+  }
+
+  /**
+   * Returns true if pause on lost focus is enabled, false otherwise.
+   *
+   * @return true if pause on lost focus is enabled
+   *
+   * @see #getLostFocusBehavior()
+   */
+  @Override
+  public boolean isPauseOnLostFocus() {
+    return getLostFocusBehavior() == LostFocusBehavior.PauseOnLostFocus;
+  }
+
+  /**
+   * Enable or disable pause on lost focus.
+   * <p>
+   * By default, pause on lost focus is enabled. If enabled, the application will stop updating when
+   * it loses focus or becomes inactive (e.g. alt-tab). For online or real-time applications, this
+   * might be undesirable, so this feature should be disabled. For other applications, it is best to
+   * keep it enabled so the CPU is not used unnecessarily.
+   *
+   * @param pauseOnLostFocus True to enable pause on lost focus, false otherwise.
+   *
+   * @see #setLostFocusBehavior(com.jme3.app.LostFocusBehavior)
+   */
+  @Override
+  public void setPauseOnLostFocus(boolean pauseOnLostFocus) {
+    if (pauseOnLostFocus) {
+      setLostFocusBehavior(LostFocusBehavior.PauseOnLostFocus);
+    } else {
+      setLostFocusBehavior(LostFocusBehavior.Disabled);
+    }
+  }
+
+  @Deprecated
+  public void setAssetManager(AssetManager assetManager) {
+    if (this.assetManager != null)
+      throw new IllegalStateException("Can only set asset manager" + " before initialization.");
+
+    this.assetManager = assetManager;
+  }
+
+  private void initAssetManager() {
+    URL assetCfgUrl = null;
+
+    if (settings != null) {
+      String assetCfg = settings.getString("AssetConfigURL");
+      if (assetCfg != null) {
+        try {
+          assetCfgUrl = new URL(assetCfg);
+        } catch (MalformedURLException ex) {
         }
         if (assetCfgUrl == null) {
-            assetCfgUrl = JmeSystem.getPlatformAssetConfigURL();
-        }
-        if (assetManager == null) {
-            assetManager = JmeSystem.newAssetManager(assetCfgUrl);
-        }
-    }
-
-    /**
-     * Set the display settings to define the display created.
-     * <p>
-     * Examples of display parameters include display pixel width and height,
-     * color bit depth, z-buffer bits, anti-aliasing samples, and update frequency.
-     * If this method is called while the application is already running, then
-     * {@link #restart() } must be called to apply the settings to the display.
-     *
-     * @param settings The settings to set.
-     */
-    @Override
-    public void setSettings(AppSettings settings) {
-        this.settings = settings;
-        if (context != null && settings.useInput() != inputEnabled) {
-            // may need to create or destroy input based
-            // on settings change
-            inputEnabled = !inputEnabled;
-            if (inputEnabled) {
-                initInput();
-            } else {
-                destroyInput();
-            }
-        } else {
-            inputEnabled = settings.useInput();
-        }
-    }
-
-    /**
-     * Sets the Timer implementation that will be used for calculating
-     * frame times.  By default, Application will use the Timer as returned
-     * by the current JmeContext implementation.
-     */
-    @Override
-    public void setTimer(Timer timer) {
-        this.timer = timer;
-
-        if (timer != null) {
-            timer.reset();
-        }
-
-        if (renderManager != null) {
-            renderManager.setTimer(timer);
-        }
-    }
-
-    @Override
-    public Timer getTimer() {
-        return timer;
-    }
-
-    private void initDisplay() {
-        // acquire important objects
-        // from the context
-        settings = context.getSettings();
-
-        // Only reset the timer if a user has not already provided one
-        if (timer == null) {
-            timer = context.getTimer();
-        }
-
-        renderer = context.getRenderer();
-    }
-
-    private void initAudio() {
-        if (settings.getAudioRenderer() != null && context.getType() != Type.Headless) {
-            audioRenderer = JmeSystem.newAudioRenderer(settings);
-            audioRenderer.initialize();
-            AudioContext.setAudioRenderer(audioRenderer);
-
-            listener = new Listener();
-            audioRenderer.setListener(listener);
-        }
-    }
-
-    /**
-     * Creates the camera to use for rendering. Default values are perspective
-     * projection with 45° field of view, with near and far values 1 and 1000
-     * units respectively.
-     */
-    private void initCamera() {
-        cam = new Camera(settings.getWidth(), settings.getHeight());
-
-        cam.setFrustumPerspective(45f, (float) cam.getWidth() / cam.getHeight(), 1f, 1000f);
-        cam.setLocation(new Vector3f(0f, 0f, 10f));
-        cam.lookAt(new Vector3f(0f, 0f, 0f), Vector3f.UNIT_Y);
-
-        renderManager = new RenderManager(renderer);
-        //Remy - 09/14/2010 set the timer in the renderManager
-        renderManager.setTimer(timer);
-
-        if (prof != null) {
-            renderManager.setAppProfiler(prof);
-        }
-
-        viewPort = renderManager.createMainView("Default", cam);
-        viewPort.setClearFlags(true, true, true);
-
-        // Create a new cam for the gui
-        Camera guiCam = new Camera(settings.getWidth(), settings.getHeight());
-        guiViewPort = renderManager.createPostView("Gui Default", guiCam);
-        guiViewPort.setClearFlags(false, false, false);
-    }
-
-    /**
-     * Initializes mouse and keyboard input. Also
-     * initializes joystick input if joysticks are enabled in the
-     * AppSettings.
-     */
-    private void initInput() {
-        mouseInput = context.getMouseInput();
-        if (mouseInput != null)
-            mouseInput.initialize();
-
-        keyInput = context.getKeyInput();
-        if (keyInput != null)
-            keyInput.initialize();
-
-        touchInput = context.getTouchInput();
-        if (touchInput != null)
-            touchInput.initialize();
-
-        if (settings.useJoysticks()) {
-            joyInput = context.getJoyInput();
-            if (joyInput != null)
-                joyInput.initialize();
-        }
-
-        inputManager = new InputManager(mouseInput, keyInput, joyInput, touchInput);
-    }
-
-    private void initStateManager() {
-        stateManager = new AppStateManager(this);
-
-        // Always register a ResetStatsState to make sure
-        // that the stats are cleared every frame
-        stateManager.attach(new ResetStatsState());
-    }
-
-    /**
-     * @return The {@link AssetManager asset manager} for this application.
-     */
-    @Override
-    public AssetManager getAssetManager() {
-        return assetManager;
-    }
-
-    /**
-     * @return the {@link InputManager input manager}.
-     */
-    @Override
-    public InputManager getInputManager() {
-        return inputManager;
-    }
-
-    /**
-     * @return the {@link AppStateManager app state manager}
-     */
-    @Override
-    public AppStateManager getStateManager() {
-        return stateManager;
-    }
-
-    /**
-     * @return the {@link RenderManager render manager}
-     */
-    @Override
-    public RenderManager getRenderManager() {
-        return renderManager;
-    }
-
-    /**
-     * @return The {@link Renderer renderer} for the application
-     */
-    @Override
-    public Renderer getRenderer() {
-        return renderer;
-    }
-
-    /**
-     * @return The {@link AudioRenderer audio renderer} for the application
-     */
-    @Override
-    public AudioRenderer getAudioRenderer() {
-        return audioRenderer;
-    }
-
-    /**
-     * @return The {@link Listener listener} object for audio
-     */
-    @Override
-    public Listener getListener() {
-        return listener;
-    }
-
-    /**
-     * @return The {@link JmeContext display context} for the application
-     */
-    @Override
-    public JmeContext getContext() {
-        return context;
-    }
-
-    /**
-     * @return The {@link Camera camera} for the application
-     */
-    @Override
-    public Camera getCamera() {
-        return cam;
-    }
-
-    /**
-     * Starts the application in {@link Type#Display display} mode.
-     *
-     * @see #start(com.jme3.system.JmeContext.Type)
-     */
-    @Override
-    public void start() {
-        start(JmeContext.Type.Display, false);
-    }
-
-    /**
-     * Starts the application in {@link Type#Display display} mode.
-     *
-     * @param waitFor true&rarr;wait for the context to be initialized,
-     * false&rarr;don't wait
-     * @see #start(com.jme3.system.JmeContext.Type)
-     */
-    @Override
-    public void start(boolean waitFor) {
-        start(JmeContext.Type.Display, waitFor);
-    }
-
-    /**
-     * Starts the application.
-     * Creating a rendering context and executing
-     * the main loop in a separate thread.
-     *
-     * @param contextType the type of context to create
-     */
-    public void start(JmeContext.Type contextType) {
-        start(contextType, false);
-    }
-
-    /**
-     * Starts the application.
-     * Creating a rendering context and executing
-     * the main loop in a separate thread.
-     *
-     * @param contextType the type of context to create
-     * @param waitFor true&rarr;wait for the context to be initialized,
-     * false&rarr;don't wait
-     */
-    public void start(JmeContext.Type contextType, boolean waitFor) {
-        if (context != null && context.isCreated()) {
-            logger.warning("start() called when application already created!");
+          assetCfgUrl = LegacyApplication.class.getClassLoader().getResource(assetCfg);
+          if (assetCfgUrl == null) {
+            logger.log(Level.SEVERE, "Unable to access AssetConfigURL in asset config:{0}",
+                assetCfg);
             return;
+          }
         }
-
-        if (settings == null) {
-            settings = new AppSettings(true);
-        }
-
-        logger.log(Level.FINE, "Starting application: {0}", getClass().getName());
-        context = JmeSystem.newContext(settings, contextType);
-        context.setSystemListener(this);
-        context.create(waitFor);
-    }
-
-    /**
-     * Sets an AppProfiler hook that will be called back for
-     * specific steps within a single update frame.  Value defaults
-     * to null.
-     *
-     * @param prof the profiler to use (alias created) or null for none
-     */
-    @Override
-    public void setAppProfiler(AppProfiler prof) {
-        this.prof = prof;
-        if (renderManager != null) {
-            renderManager.setAppProfiler(prof);
-        }
-    }
-
-    /**
-     * Returns the current AppProfiler hook, or null if none is set.
-     */
-    @Override
-    public AppProfiler getAppProfiler() {
-        return prof;
-    }
-
-    /**
-     * Initializes the application's canvas for use.
-     * <p>
-     * After calling this method, cast the {@link #getContext()} context to
-     * JmeCanvasContext,
-     * then acquire the canvas with JmeCanvasContext.getCanvas()
-     * and attach it to an AWT/Swing Frame.
-     * The rendering thread will start when the canvas becomes visible on
-     * screen, however if you wish to start the context immediately you
-     * may call {@link #startCanvas() } to force the rendering thread
-     * to start.
-     *
-     * @see Type#Canvas
-     */
-    public void createCanvas() {
-        if (context != null && context.isCreated()) {
-            logger.warning("createCanvas() called when application already created!");
-            return;
-        }
-
-        if (settings == null) {
-            settings = new AppSettings(true);
-        }
-
-        if (logger.isLoggable(Level.FINE)) {
-            logger.log(Level.FINE, "Starting application: {0}", getClass().getName());
-        }
-        context = JmeSystem.newContext(settings, JmeContext.Type.Canvas);
-        context.setSystemListener(this);
-    }
-
-    /**
-     * Starts the rendering thread after createCanvas() has been called.
-     * <p>
-     * Same as calling startCanvas(false)
-     *
-     * @see #startCanvas(boolean)
-     */
-    public void startCanvas() {
-        startCanvas(false);
-    }
-
-    /**
-     * Starts the rendering thread after createCanvas() has been called.
-     * <p>
-     * Calling this method is optional, the canvas will start automatically
-     * when it becomes visible.
-     *
-     * @param waitFor If true, the current thread will block until the
-     * rendering thread is running
-     */
-    public void startCanvas(boolean waitFor) {
-        context.create(waitFor);
-    }
-
-    /**
-     * Internal use only.
-     */
-    @Override
-    public void reshape(int w, int h) {
-        if (renderManager != null) {
-            renderManager.notifyReshape(w, h);
-        }
-    }
-
-
-    @Override
-    public void rescale(float x, float y){
-        if (renderManager != null) {
-            renderManager.notifyRescale(x, y);
-        }
-    }
-
-    /**
-     * Restarts the context, applying any changed settings.
-     * <p>
-     * Changes to the {@link AppSettings} of this Application are not
-     * applied immediately; calling this method forces the context
-     * to restart, applying the new settings.
-     */
-    @Override
-    public void restart() {
-        context.setSettings(settings);
-        context.restart();
-    }
-
-    /**
-     * Requests the context to close, shutting down the main loop
-     * and making necessary cleanup operations.
-     *
-     * Same as calling stop(false)
-     *
-     * @see #stop(boolean)
-     */
-    @Override
-    public void stop() {
-        stop(false);
-    }
-
-    /**
-     * Requests the context to close, shutting down the main loop
-     * and making necessary cleanup operations.
-     * After the application has stopped, it cannot be used anymore.
-     *
-     * @param waitFor true&rarr;wait for the context to be fully destroyed,
-     * true&rarr;don't wait
-     */
-    @Override
-    public void stop(boolean waitFor) {
-        logger.log(Level.FINE, "Closing application: {0}", getClass().getName());
-        context.destroy(waitFor);
-    }
-
-    /**
-     * Do not call manually.
-     * Callback from ContextListener.
-     * <p>
-     * Initializes the <code>Application</code>, by creating a display and
-     * default camera. If display settings are not specified, a default
-     * 640x480 display is created. Default values are used for the camera;
-     * perspective projection with 45° field of view, with near
-     * and far values 1 and 1000 units respectively.
-     */
-    @Override
-    public void initialize() {
-        if (assetManager == null) {
-            initAssetManager();
-        }
-
-        initDisplay();
-        initCamera();
-
-        if (inputEnabled) {
-            initInput();
-        }
-        initAudio();
-
-        // update timer so that the next delta is not too large
-//        timer.update();
-        timer.reset();
-
-        // user code here
-    }
-
-    /**
-     * Internal use only.
-     */
-    @Override
-    public void handleError(String errMsg, Throwable t) {
-        // Print error to log.
-        logger.log(Level.SEVERE, errMsg, t);
-        // Display error message on screen if not in headless mode
-        if (context.getType() != JmeContext.Type.Headless) {
-            if (t != null) {
-                JmeSystem.handleErrorMessage(errMsg + "\n" + t.getClass().getSimpleName()
-                        + (t.getMessage() != null ? ": " + t.getMessage() : ""));
-            } else {
-                JmeSystem.handleErrorMessage(errMsg);
-            }
-        }
-
-        stop(); // stop the application
-    }
-
-    /**
-     * Internal use only.
-     */
-    @Override
-    public void gainFocus() {
-        if (lostFocusBehavior != LostFocusBehavior.Disabled) {
-            if (lostFocusBehavior == LostFocusBehavior.PauseOnLostFocus) {
-                paused = false;
-            }
-            context.setAutoFlushFrames(true);
-            if (inputManager != null) {
-                inputManager.reset();
-            }
-        }
-    }
-
-    /**
-     * Internal use only.
-     */
-    @Override
-    public void loseFocus() {
-        if (lostFocusBehavior != LostFocusBehavior.Disabled) {
-            if (lostFocusBehavior == LostFocusBehavior.PauseOnLostFocus) {
-                paused = true;
-            }
-            context.setAutoFlushFrames(false);
-        }
-    }
-
-    /**
-     * Internal use only.
-     */
-    @Override
-    public void requestClose(boolean esc) {
-        context.destroy(false);
-    }
-
-    /**
-     * Enqueues a task/callable object to execute in the jME3
-     * rendering thread.
-     * <p>
-     * Callables are executed right at the beginning of the main loop.
-     * They are executed even if the application is currently paused
-     * or out of focus.
-     *
-     * @param <V> type of result returned by the Callable
-     * @param callable The callable to run in the main jME3 thread
-     * @return a new instance
-     */
-    @Override
-    public <V> Future<V> enqueue(Callable<V> callable) {
-        AppTask<V> task = new AppTask<>(callable);
-        taskQueue.add(task);
-        return task;
-    }
-
-    /**
-     * Enqueues a runnable object to execute in the jME3
-     * rendering thread.
-     * <p>
-     * Runnables are executed right at the beginning of the main loop.
-     * They are executed even if the application is currently paused
-     * or out of focus.
-     *
-     * @param runnable The runnable to run in the main jME3 thread
-     */
-    @Override
-    @SuppressWarnings("unchecked")
-    public void enqueue(Runnable runnable) {
-        enqueue(new RunnableWrapper(runnable));
-    }
-
-    /**
-     * Runs tasks enqueued via {@link #enqueue(Callable)}
-     */
-    protected void runQueuedTasks() {
-        AppTask<?> task;
-        while ((task = taskQueue.poll()) != null) {
-            if (!task.isCancelled()) {
-                task.invoke();
-            }
-        }
-    }
-
-    /**
-     * Do not call manually.
-     * Callback from ContextListener.
-     */
-    @Override
-    public void update() {
-        // Make sure the audio renderer is available to callables
-        AudioContext.setAudioRenderer(audioRenderer);
-
-        if (prof != null)
-            prof.appStep(AppStep.QueuedTasks);
-        runQueuedTasks();
-
-        if (speed == 0 || paused)
-            return;
-
-        timer.update();
-
-        if (inputEnabled) {
-            if (prof != null)
-                prof.appStep(AppStep.ProcessInput);
-            inputManager.update(timer.getTimePerFrame());
-        }
-
-        if (audioRenderer != null) {
-            if (prof != null)
-                prof.appStep(AppStep.ProcessAudio);
-            audioRenderer.update(timer.getTimePerFrame());
-        }
-
-        // user code here
-    }
-
-    protected void destroyInput() {
-        if (mouseInput != null)
-            mouseInput.destroy();
-
-        if (keyInput != null)
-            keyInput.destroy();
-
-        if (joyInput != null)
-            joyInput.destroy();
-
-        if (touchInput != null)
-            touchInput.destroy();
-
-        inputManager = null;
-    }
-
-    /**
-     * Do not call manually.
-     * Callback from ContextListener.
-     */
-    @Override
-    public void destroy() {
-        stateManager.cleanup();
-
+      }
+    }
+    if (assetCfgUrl == null) {
+      assetCfgUrl = JmeSystem.getPlatformAssetConfigURL();
+    }
+    if (assetManager == null) {
+      assetManager = JmeSystem.newAssetManager(assetCfgUrl);
+    }
+  }
+
+  /**
+   * Set the display settings to define the display created.
+   * <p>
+   * Examples of display parameters include display pixel width and height, color bit depth,
+   * z-buffer bits, anti-aliasing samples, and update frequency. If this method is called while the
+   * application is already running, then {@link #restart() } must be called to apply the settings
+   * to the display.
+   *
+   * @param settings The settings to set.
+   */
+  @Override
+  public void setSettings(AppSettings settings) {
+    this.settings = settings;
+    if (context != null && settings.useInput() != inputEnabled) {
+      // may need to create or destroy input based
+      // on settings change
+      inputEnabled = !inputEnabled;
+      if (inputEnabled) {
+        initInput();
+      } else {
         destroyInput();
-        if (audioRenderer != null)
-            audioRenderer.cleanup();
-
-        timer.reset();
+      }
+    } else {
+      inputEnabled = settings.useInput();
     }
+  }
 
-    /**
-     * @return The GUI viewport. Which is used for the on screen
-     * statistics and FPS.
-     */
-    @Override
-    public ViewPort getGuiViewPort() {
-        return guiViewPort;
-    }
+  /**
+   * Sets the Timer implementation that will be used for calculating frame times. By default,
+   * Application will use the Timer as returned by the current JmeContext implementation.
+   */
+  @Override
+  public void setTimer(Timer timer) {
+    this.timer = timer;
 
-    @Override
-    public ViewPort getViewPort() {
-        return viewPort;
+    if (timer != null) {
+      timer.reset();
     }
 
-    private class RunnableWrapper implements Callable {
-        private final Runnable runnable;
+    if (renderManager != null) {
+      renderManager.setTimer(timer);
+    }
+  }
 
-        public RunnableWrapper(Runnable runnable) {
-            this.runnable = runnable;
-        }
+  @Override
+  public Timer getTimer() {
+    return timer;
+  }
+
+  private void initDisplay() {
+    // acquire important objects
+    // from the context
+    settings = context.getSettings();
+
+    // Only reset the timer if a user has not already provided one
+    if (timer == null) {
+      timer = context.getTimer();
+    }
+
+    renderer = context.getRenderer();
+  }
+
+  private void initAudio() {
+    if (settings.getAudioRenderer() != null && context.getType() != Type.Headless) {
+      audioRenderer = JmeSystem.newAudioRenderer(settings);
+      audioRenderer.initialize();
+      AudioContext.setAudioRenderer(audioRenderer);
+
+      listener = new Listener();
+      audioRenderer.setListener(listener);
+    }
+  }
+
+  /**
+   * Creates the camera to use for rendering. Default values are perspective projection with 45°
+   * field of view, with near and far values 1 and 1000 units respectively.
+   */
+  private void initCamera() {
+    cam = new Camera(settings.getWidth(), settings.getHeight());
+
+    cam.setFrustumPerspective(45f, (float) cam.getWidth() / cam.getHeight(), 1f, 1000f);
+    cam.setLocation(new Vector3f(0f, 0f, 10f));
+    cam.lookAt(new Vector3f(0f, 0f, 0f), Vector3f.UNIT_Y);
+
+    renderManager = new RenderManager(renderer);
+    // Remy - 09/14/2010 set the timer in the renderManager
+    renderManager.setTimer(timer);
+
+    if (prof != null) {
+      renderManager.setAppProfiler(prof);
+    }
+
+    viewPort = renderManager.createMainView("Default", cam);
+    viewPort.setClearFlags(true, true, true);
+
+    // Create a new cam for the gui
+    Camera guiCam = new Camera(settings.getWidth(), settings.getHeight());
+    guiViewPort = renderManager.createPostView("Gui Default", guiCam);
+    guiViewPort.setClearFlags(false, false, false);
+  }
+
+  /**
+   * Initializes mouse and keyboard input. Also initializes joystick input if joysticks are enabled
+   * in the AppSettings.
+   */
+  private void initInput() {
+    mouseInput = context.getMouseInput();
+    if (mouseInput != null)
+      mouseInput.initialize();
+
+    keyInput = context.getKeyInput();
+    if (keyInput != null)
+      keyInput.initialize();
+
+    touchInput = context.getTouchInput();
+    if (touchInput != null)
+      touchInput.initialize();
+
+    if (settings.useJoysticks()) {
+      joyInput = context.getJoyInput();
+      if (joyInput != null)
+        joyInput.initialize();
+    }
+
+    inputManager = new InputManager(mouseInput, keyInput, joyInput, touchInput);
+  }
+
+  private void initStateManager() {
+    stateManager = new AppStateManager(this);
+
+    // Always register a ResetStatsState to make sure
+    // that the stats are cleared every frame
+    stateManager.attach(new ResetStatsState());
+  }
+
+  /**
+   * @return The {@link AssetManager asset manager} for this application.
+   */
+  @Override
+  public AssetManager getAssetManager() {
+    return assetManager;
+  }
+
+  /**
+   * @return the {@link InputManager input manager}.
+   */
+  @Override
+  public InputManager getInputManager() {
+    return inputManager;
+  }
+
+  /**
+   * @return the {@link AppStateManager app state manager}
+   */
+  @Override
+  public AppStateManager getStateManager() {
+    return stateManager;
+  }
+
+  /**
+   * @return the {@link RenderManager render manager}
+   */
+  @Override
+  public RenderManager getRenderManager() {
+    return renderManager;
+  }
+
+  /**
+   * @return The {@link Renderer renderer} for the application
+   */
+  @Override
+  public Renderer getRenderer() {
+    return renderer;
+  }
+
+  /**
+   * @return The {@link AudioRenderer audio renderer} for the application
+   */
+  @Override
+  public AudioRenderer getAudioRenderer() {
+    return audioRenderer;
+  }
+
+  /**
+   * @return The {@link Listener listener} object for audio
+   */
+  @Override
+  public Listener getListener() {
+    return listener;
+  }
+
+  /**
+   * @return The {@link JmeContext display context} for the application
+   */
+  @Override
+  public JmeContext getContext() {
+    return context;
+  }
+
+  /**
+   * @return The {@link Camera camera} for the application
+   */
+  @Override
+  public Camera getCamera() {
+    return cam;
+  }
+
+  /**
+   * Starts the application in {@link Type#Display display} mode.
+   *
+   * @see #start(com.jme3.system.JmeContext.Type)
+   */
+  @Override
+  public void start() {
+    start(JmeContext.Type.Display, false);
+  }
+
+  /**
+   * Starts the application in {@link Type#Display display} mode.
+   *
+   * @param waitFor true&rarr;wait for the context to be initialized, false&rarr;don't wait
+   * @see #start(com.jme3.system.JmeContext.Type)
+   */
+  @Override
+  public void start(boolean waitFor) {
+    start(JmeContext.Type.Display, waitFor);
+  }
+
+  /**
+   * Starts the application. Creating a rendering context and executing the main loop in a separate
+   * thread.
+   *
+   * @param contextType the type of context to create
+   */
+  public void start(JmeContext.Type contextType) {
+    start(contextType, false);
+  }
+
+  /**
+   * Starts the application. Creating a rendering context and executing the main loop in a separate
+   * thread.
+   *
+   * @param contextType the type of context to create
+   * @param waitFor true&rarr;wait for the context to be initialized, false&rarr;don't wait
+   */
+  public void start(JmeContext.Type contextType, boolean waitFor) {
+    if (context != null && context.isCreated()) {
+      logger.warning("start() called when application already created!");
+      return;
+    }
+
+    if (settings == null) {
+      settings = new AppSettings(true);
+    }
+
+    logger.log(Level.FINE, "Starting application: {0}", getClass().getName());
+    context = JmeSystem.newContext(settings, contextType);
+    context.setSystemListener(this);
+    context.create(waitFor);
+  }
+
+  /**
+   * Sets an AppProfiler hook that will be called back for specific steps within a single update
+   * frame. Value defaults to null.
+   *
+   * @param prof the profiler to use (alias created) or null for none
+   */
+  @Override
+  public void setAppProfiler(AppProfiler prof) {
+    this.prof = prof;
+    if (renderManager != null) {
+      renderManager.setAppProfiler(prof);
+    }
+  }
+
+  /**
+   * Returns the current AppProfiler hook, or null if none is set.
+   */
+  @Override
+  public AppProfiler getAppProfiler() {
+    return prof;
+  }
+
+  /**
+   * Initializes the application's canvas for use.
+   * <p>
+   * After calling this method, cast the {@link #getContext()} context to JmeCanvasContext, then
+   * acquire the canvas with JmeCanvasContext.getCanvas() and attach it to an AWT/Swing Frame. The
+   * rendering thread will start when the canvas becomes visible on screen, however if you wish to
+   * start the context immediately you may call {@link #startCanvas() } to force the rendering
+   * thread to start.
+   *
+   * @see Type#Canvas
+   */
+  public void createCanvas() {
+    if (context != null && context.isCreated()) {
+      logger.warning("createCanvas() called when application already created!");
+      return;
+    }
+
+    if (settings == null) {
+      settings = new AppSettings(true);
+    }
+
+    if (logger.isLoggable(Level.FINE)) {
+      logger.log(Level.FINE, "Starting application: {0}", getClass().getName());
+    }
+    context = JmeSystem.newContext(settings, JmeContext.Type.Canvas);
+    context.setSystemListener(this);
+  }
+
+  /**
+   * Starts the rendering thread after createCanvas() has been called.
+   * <p>
+   * Same as calling startCanvas(false)
+   *
+   * @see #startCanvas(boolean)
+   */
+  public void startCanvas() {
+    startCanvas(false);
+  }
+
+  /**
+   * Starts the rendering thread after createCanvas() has been called.
+   * <p>
+   * Calling this method is optional, the canvas will start automatically when it becomes visible.
+   *
+   * @param waitFor If true, the current thread will block until the rendering thread is running
+   */
+  public void startCanvas(boolean waitFor) {
+    context.create(waitFor);
+  }
+
+  /**
+   * Internal use only.
+   */
+  @Override
+  public void reshape(int w, int h) {
+    if (renderManager != null) {
+      renderManager.notifyReshape(w, h);
+    }
+  }
+
+
+  @Override
+  public void rescale(float x, float y) {
+    if (renderManager != null) {
+      renderManager.notifyRescale(x, y);
+    }
+  }
+
+  /**
+   * Restarts the context, applying any changed settings.
+   * <p>
+   * Changes to the {@link AppSettings} of this Application are not applied immediately; calling
+   * this method forces the context to restart, applying the new settings.
+   */
+  @Override
+  public void restart() {
+    context.setSettings(settings);
+    context.restart();
+  }
+
+  /**
+   * Requests the context to close, shutting down the main loop and making necessary cleanup
+   * operations.
+   *
+   * Same as calling stop(false)
+   *
+   * @see #stop(boolean)
+   */
+  @Override
+  public void stop() {
+    stop(false);
+  }
+
+  /**
+   * Requests the context to close, shutting down the main loop and making necessary cleanup
+   * operations. After the application has stopped, it cannot be used anymore.
+   *
+   * @param waitFor true&rarr;wait for the context to be fully destroyed, true&rarr;don't wait
+   */
+  @Override
+  public void stop(boolean waitFor) {
+    logger.log(Level.FINE, "Closing application: {0}", getClass().getName());
+    context.destroy(waitFor);
+  }
+
+  /**
+   * Do not call manually. Callback from ContextListener.
+   * <p>
+   * Initializes the <code>Application</code>, by creating a display and default camera. If display
+   * settings are not specified, a default 640x480 display is created. Default values are used for
+   * the camera; perspective projection with 45° field of view, with near and far values 1 and 1000
+   * units respectively.
+   */
+  @Override
+  public void initialize() {
+    if (assetManager == null) {
+      initAssetManager();
+    }
+
+    initDisplay();
+    initCamera();
+
+    if (inputEnabled) {
+      initInput();
+    }
+    initAudio();
+
+    // update timer so that the next delta is not too large
+    // timer.update();
+    timer.reset();
+
+    // user code here
+  }
+
+  /**
+   * Internal use only.
+   */
+  @Override
+  public void handleError(String errMsg, Throwable t) {
+    // Print error to log.
+    logger.log(Level.SEVERE, errMsg, t);
+    // Display error message on screen if not in headless mode
+    if (context.getType() != JmeContext.Type.Headless) {
+      if (t != null) {
+        JmeSystem.handleErrorMessage(errMsg + "\n" + t.getClass().getSimpleName()
+            + (t.getMessage() != null ? ": " + t.getMessage() : ""));
+      } else {
+        JmeSystem.handleErrorMessage(errMsg);
+      }
+    }
+
+    stop(); // stop the application
+  }
+
+  /**
+   * Internal use only.
+   */
+  @Override
+  public void gainFocus() {
+    if (lostFocusBehavior != LostFocusBehavior.Disabled) {
+      if (lostFocusBehavior == LostFocusBehavior.PauseOnLostFocus) {
+        paused = false;
+      }
+      context.setAutoFlushFrames(true);
+      if (inputManager != null) {
+        inputManager.reset();
+      }
+    }
+  }
+
+  /**
+   * Internal use only.
+   */
+  @Override
+  public void loseFocus() {
+    if (lostFocusBehavior != LostFocusBehavior.Disabled) {
+      if (lostFocusBehavior == LostFocusBehavior.PauseOnLostFocus) {
+        paused = true;
+      }
+      context.setAutoFlushFrames(false);
+    }
+  }
+
+  /**
+   * Internal use only.
+   */
+  @Override
+  public void requestClose(boolean esc) {
+    context.destroy(false);
+  }
+
+  /**
+   * Enqueues a task/callable object to execute in the jME3 rendering thread.
+   * <p>
+   * Callables are executed right at the beginning of the main loop. They are executed even if the
+   * application is currently paused or out of focus.
+   *
+   * @param <V> type of result returned by the Callable
+   * @param callable The callable to run in the main jME3 thread
+   * @return a new instance
+   */
+  @Override
+  public <V> Future<V> enqueue(Callable<V> callable) {
+    AppTask<V> task = new AppTask<>(callable);
+    taskQueue.add(task);
+    return task;
+  }
+
+  /**
+   * Enqueues a runnable object to execute in the jME3 rendering thread.
+   * <p>
+   * Runnables are executed right at the beginning of the main loop. They are executed even if the
+   * application is currently paused or out of focus.
+   *
+   * @param runnable The runnable to run in the main jME3 thread
+   */
+  @Override
+  @SuppressWarnings("unchecked")
+  public void enqueue(Runnable runnable) {
+    enqueue(new RunnableWrapper(runnable));
+  }
+
+  /**
+   * Runs tasks enqueued via {@link #enqueue(Callable)}
+   */
+  protected void runQueuedTasks() {
+    AppTask<?> task;
+    while ((task = taskQueue.poll()) != null) {
+      if (!task.isCancelled()) {
+        task.invoke();
+      }
+    }
+  }
+
+  /**
+   * Do not call manually. Callback from ContextListener.
+   */
+  @Override
+  public void update() {
+    // Make sure the audio renderer is available to callables
+    AudioContext.setAudioRenderer(audioRenderer);
+
+    if (prof != null)
+      prof.appStep(AppStep.QueuedTasks);
+    runQueuedTasks();
+
+    if (speed == 0 || paused)
+      return;
+
+    timer.update();
+
+    if (inputEnabled) {
+      if (prof != null)
+        prof.appStep(AppStep.ProcessInput);
+      inputManager.update(timer.getTimePerFrame());
+    }
+
+    if (audioRenderer != null) {
+      if (prof != null)
+        prof.appStep(AppStep.ProcessAudio);
+      audioRenderer.update(timer.getTimePerFrame());
+    }
+
+    // user code here
+  }
+
+  protected void destroyInput() {
+    if (mouseInput != null)
+      mouseInput.destroy();
+
+    if (keyInput != null)
+      keyInput.destroy();
+
+    if (joyInput != null)
+      joyInput.destroy();
+
+    if (touchInput != null)
+      touchInput.destroy();
+
+    inputManager = null;
+  }
+
+  /**
+   * Do not call manually. Callback from ContextListener.
+   */
+  @Override
+  public void destroy() {
+    stateManager.cleanup();
+
+    destroyInput();
+    if (audioRenderer != null)
+      audioRenderer.cleanup();
+
+    timer.reset();
+  }
+
+  /**
+   * @return The GUI viewport. Which is used for the on screen statistics and FPS.
+   */
+  @Override
+  public ViewPort getGuiViewPort() {
+    return guiViewPort;
+  }
+
+  @Override
+  public ViewPort getViewPort() {
+    return viewPort;
+  }
+
+  private class RunnableWrapper implements Callable {
+    private final Runnable runnable;
+
+    public RunnableWrapper(Runnable runnable) {
+      this.runnable = runnable;
+    }
+
+    @Override
+    public Object call() {
+      runnable.run();
+      return null;
+    }
+  }
+
+  /**
+   * This call will return a list of Monitors that glfwGetMonitors() returns and information about
+   * the monitor, like width, height, and refresh rate.
+   * 
+   * @return returns a list of monitors and their information.
+   */
+  public Monitors getMonitors() {
+    return context.getMonitors();
+  }
 
-        @Override
-        public Object call() {
-            runnable.run();
-            return null;
-        }
-    }
-    
-    /**
-     * This call will return a list of Monitors that glfwGetMonitors()
-     * returns and information about the monitor, like width, height, 
-     * and refresh rate.
-     * 
-     * @return returns a list of monitors and their information.
-     */
-    public Monitors getMonitors()
-    {
-       return context.getMonitors();
-    }
-    
-    /**
-     * Use this to get the positional number of the primary
-     * monitor from the glfwGetMonitors() function call.
-     * 
-     * @return the position of the value in the arraylist of
-     *         the primary monitor.
-     */
-    public int getPrimaryMonitor()
-    {
-       return context.getPrimaryMonitor();
-    }
+  /**
+   * Use this to get the positional number of the primary monitor from the glfwGetMonitors()
+   * function call.
+   * 
+   * @return the position of the value in the arraylist of the primary monitor.
+   */
+  public int getPrimaryMonitor() {
+    return context.getPrimaryMonitor();
+  }
 }

+ 11 - 9
jme3-core/src/main/java/com/jme3/system/AppSettings.java

@@ -1485,27 +1485,29 @@ public final class AppSettings extends HashMap<String, Object> {
     /**
      * Gets the monitor number used when creating a window.
      *
-     * <p>This setting is used only with LWJGL3, it defines which monitor
-     * to use when creating a OpenGL window.
+     * <p>
+     * This setting is used only with LWJGL3, it defines which monitor to use when creating a OpenGL
+     * window.
      *
      * @return the desired monitor used when creating a OpenGL window
      * @see #setMonitor(long)
      */
     public int getMonitor() {
-        return getInteger("Monitor");
+      return getInteger("Monitor");
     }
 
     /**
-     * Sets the monitor number used when creating a window.  The position
-     * number is the number in the list of monitors GlfwGetMonitors returns.
+     * Sets the monitor number used when creating a window. The position number is the number in the
+     * list of monitors GlfwGetMonitors returns.
      *
-     * <p>This setting is used only with LWJGL3, it defines which monitor
-     * to use when creating a OpenGL window. its default value is 0.
+     * <p>
+     * This setting is used only with LWJGL3, it defines which monitor to use when creating a OpenGL
+     * window. its default value is 0.
      *
      * @param mon the desired monitor used when creating a OpenGL window
      * 
      */
     public void setMonitor(int mon) {
-        putInteger("Monitor", mon);
+      putInteger("Monitor", mon);
     }
-}
+  }

+ 7 - 9
jme3-core/src/main/java/com/jme3/system/JmeContext.java

@@ -227,20 +227,18 @@ public interface JmeContext {
     public int getWindowYPosition();
 
     /**
-     * This call will return a list of Monitors that glfwGetMonitors()
-     * returns and information about the monitor, like width, height, 
-     * and refresh rate.
+     * This call will return a list of Monitors that glfwGetMonitors() returns and information about
+     * the monitor, like width, height, and refresh rate.
      * 
      * @return returns a list of monitors and their information.
      */
     public Monitors getMonitors();
 
     /**
-     * Use this to get the positional number of the primary
-     * monitor from the glfwGetMonitors() function call.
+     * Use this to get the positional number of the primary monitor from the glfwGetMonitors()
+     * function call.
      * 
-     * @return the position of the value in the arraylist of
-     *         the primary monitor.
-     */    
+     * @return the position of the value in the arraylist of the primary monitor.
+     */
     public int getPrimaryMonitor();
-}
+  }

+ 47 - 54
jme3-core/src/main/java/com/jme3/system/MonitorInfo.java

@@ -1,73 +1,66 @@
 /*
- * Copyright (c) 2009-2023 jMonkeyEngine
- * All rights reserved.
+ * Copyright (c) 2009-2023 jMonkeyEngine All rights reserved.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * Redistribution and use in source and binary forms, with or without modification, are permitted
+ * provided that the following conditions are met:
  *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions
+ * and the following disclaimer.
  *
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials provided with
+ * the distribution.
  *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors may be used to endorse or
+ * promote products derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 package com.jme3.system;
 
 /**
- * This class holds information about the monitor that was
- * returned by glfwGetMonitors() calls in the context
- * class
+ * This class holds information about the monitor that was returned by glfwGetMonitors() calls in
+ * the context class
  * 
  * @author Kevin Bales
  */
 public class MonitorInfo {
-   
-   /**
-    * monitorID - monitor id that was return from Lwjgl3.
-    */
-   public long monitorID = 0;
 
-   /**
-    * width - width that was return from Lwjgl3.
-    */
-   public int width = 1080;
+  /**
+   * monitorID - monitor id that was return from Lwjgl3.
+   */
+  public long monitorID = 0;
 
-   /**
-    * height - height that was return from Lwjgl3.
-    */
-   public int height = 1920;
+  /**
+   * width - width that was return from Lwjgl3.
+   */
+  public int width = 1080;
 
-   /**
-    * rate - refresh rate that was return from Lwjgl3.
-    */
-   public int rate = 60;
-   
-   /**
-    * primary - indicates if the monitor is the primary monitor.
-    */
-   public boolean primary = false;
-   
-   /**
-    * name - monitor name that was return from Lwjgl3.
-    */
-   public String name = "Generic Monitor";
+  /**
+   * height - height that was return from Lwjgl3.
+   */
+  public int height = 1920;
+
+  /**
+   * rate - refresh rate that was return from Lwjgl3.
+   */
+  public int rate = 60;
+
+  /**
+   * primary - indicates if the monitor is the primary monitor.
+   */
+  public boolean primary = false;
+
+  /**
+   * name - monitor name that was return from Lwjgl3.
+   */
+  public String name = "Generic Monitor";
 
 }

+ 83 - 97
jme3-core/src/main/java/com/jme3/system/Monitors.java

@@ -1,119 +1,105 @@
 /*
- * Copyright (c) 2009-2023 jMonkeyEngine
- * All rights reserved.
+ * Copyright (c) 2009-2023 jMonkeyEngine All rights reserved.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * Redistribution and use in source and binary forms, with or without modification, are permitted
+ * provided that the following conditions are met:
  *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions
+ * and the following disclaimer.
  *
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials provided with
+ * the distribution.
  *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors may be used to endorse or
+ * promote products derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 package com.jme3.system;
 
 import java.util.ArrayList;
 
 /**
- * This class holds all information about all monitors that where
- * return from the glfwGetMonitors() call.  It stores them into
- * an <ArrayList>
+ * This class holds all information about all monitors that where return from the glfwGetMonitors()
+ * call. It stores them into an <ArrayList>
  * 
  * @author Kevin Bales
  */
 public class Monitors {
 
-   private ArrayList<MonitorInfo> monitors = new ArrayList<MonitorInfo>();
-   
-   public int addNewMonitor(long monitorID)
-   {
-      MonitorInfo info = new MonitorInfo();
-      info.monitorID = monitorID;
-      monitors.add(info);
-      return monitors.size() - 1;
-   }
-   
-   /**
-    * This function returns the size of the monitor ArrayList
-    * @return the 
-    */
-   public int size()
-   {
-      return monitors.size();
-   }
-   
-   /**
-    * Call to get monitor information on a certain monitor.
-    * 
-    * @param pos the position in the arraylist of the monitor
-    *        information that you want to get.
-    * @return  returns the MonitorInfo data for the monitor
-    *          called for.
-    */
-   public MonitorInfo get(int pos)
-   {
-      if (pos < monitors.size())
-         return monitors.get(pos);
-      
-      return null;
-   }
+  private ArrayList<MonitorInfo> monitors = new ArrayList<MonitorInfo>();
 
-   /**
-    * Set information about this monitor stored in monPos position
-    * in the array list.
-    * 
-    * @param monPos  arraylist position of monitor to update
-    * @param width   the current width the monitor is displaying
-    * @param height  the current height the monitor is displaying
-    * @param rate    the current refresh rate the monitor is set to
-    */
-   public void setInfo(int monPos, String name, int width, int height, int rate) {
-      if (monPos < monitors.size() ) {
-         MonitorInfo info = monitors.get(monPos);
-         if (info != null) {
-            info.width = width;
-            info.height = height;
-            info.rate = rate;
-            info.name = name;
-         }
-      }
-   }
+  public int addNewMonitor(long monitorID) {
+    MonitorInfo info = new MonitorInfo();
+    info.monitorID = monitorID;
+    monitors.add(info);
+    return monitors.size() - 1;
+  }
+
+  /**
+   * This function returns the size of the monitor ArrayList
+   * 
+   * @return the
+   */
+  public int size() {
+    return monitors.size();
+  }
+
+  /**
+   * Call to get monitor information on a certain monitor.
+   * 
+   * @param pos the position in the arraylist of the monitor information that you want to get.
+   * @return returns the MonitorInfo data for the monitor called for.
+   */
+  public MonitorInfo get(int pos) {
+    if (pos < monitors.size())
+      return monitors.get(pos);
+
+    return null;
+  }
 
-   /**
-    * This function will mark a certain monitor as the
-    * primary monitor.
-    *  
-    * @param monPos the position in the arraylist of which
-    *        monitor is the primary monitor
-    */
-   public void setPrimaryMonitor(int monPos) {
-      if (monPos < monitors.size() ) {
-         MonitorInfo info = monitors.get(monPos);
-         if (info != null)
-            info.primary = true;
+  /**
+   * Set information about this monitor stored in monPos position in the array list.
+   * 
+   * @param monPos arraylist position of monitor to update
+   * @param width the current width the monitor is displaying
+   * @param height the current height the monitor is displaying
+   * @param rate the current refresh rate the monitor is set to
+   */
+  public void setInfo(int monPos, String name, int width, int height, int rate) {
+    if (monPos < monitors.size()) {
+      MonitorInfo info = monitors.get(monPos);
+      if (info != null) {
+        info.width = width;
+        info.height = height;
+        info.rate = rate;
+        info.name = name;
       }
-      
-   }
-   
-   
+    }
+  }
+
+  /**
+   * This function will mark a certain monitor as the primary monitor.
+   * 
+   * @param monPos the position in the arraylist of which monitor is the primary monitor
+   */
+  public void setPrimaryMonitor(int monPos) {
+    if (monPos < monitors.size()) {
+      MonitorInfo info = monitors.get(monPos);
+      if (info != null)
+        info.primary = true;
+    }
+
+  }
+
+
 
 }

+ 6 - 6
jme3-core/src/main/java/com/jme3/system/NullContext.java

@@ -307,15 +307,15 @@ public class NullContext implements JmeContext, Runnable {
         throw new UnsupportedOperationException("null context");
     }
 
-   @Override
-   public Monitors getMonitors() {
+    @Override
+    public Monitors getMonitors() {
       // TODO Auto-generated method stub
       return null;
-   }
+    }
 
-   @Override
-   public int getPrimaryMonitor() {
+    @Override
+    public int getPrimaryMonitor() {
       // TODO Auto-generated method stub
       return 0;
-   }
+    }
 }

+ 11 - 11
jme3-desktop/src/main/java/com/jme3/system/awt/AwtPanelsContext.java

@@ -329,15 +329,15 @@ public class AwtPanelsContext implements JmeContext {
         return inputSource.getY();
     }
 
-   @Override
-   public Monitors getMonitors() {
-      // TODO Auto-generated method stub
-      return null;
-   }
-
-   @Override
-   public int getPrimaryMonitor() {
-      // TODO Auto-generated method stub
-      return 0;
-   }
+    @Override
+    public Monitors getMonitors() {
+       // TODO Auto-generated method stub
+       return null;
+    }
+
+    @Override
+    public int getPrimaryMonitor() {
+       // TODO Auto-generated method stub
+       return 0;
+    }
 }

+ 164 - 175
jme3-examples/src/main/java/jme3test/app/TestMonitorApp.java

@@ -53,199 +53,188 @@ import com.jme3.system.MonitorInfo;
 import com.jme3.system.Monitors;
 
 /**
- * Tests the capability to change which monitor the window
- * will be created on.  Also,  shows that you can force
- * JME to center the window. Also, it shows to to force JME to
- * set the window to x,y coords.  Center window and window 
- * position doesn't apply if in fullscreen.
+ * Tests the capability to change which monitor the window will be created on.
+ * Also, shows that you can force JME to center the window. Also, it shows to to
+ * force JME to set the window to x,y coords. Center window and window position
+ * doesn't apply if in fullscreen.
  * 
  * @author Kevin Bales
  */
-public class TestMonitorApp extends SimpleApplication implements ActionListener {
-    
-    private BitmapText txt;
-    private BitmapText selectedMonitorTxt;
-    private BitmapText fullScreenTxt;
-    private int monitorSelected = 0;
-    private Monitors monitors = null;
-    
-    public static void main(String[] args){
-        TestMonitorApp app = new TestMonitorApp();
-        AppSettings settings = new AppSettings(true);
-        settings.setResizable(false);
-        app.setShowSettings(true);
-        settings.setRenderer(AppSettings.LWJGL_OPENGL33);
-        settings.setMonitor(0);
-        settings.setResolution(800, 600);
-        
-        settings.setFullscreen(true);
-
-        //Force JME to center the window, this only applies if it is
-        //not fullscreen.
-        settings.setCenterWindow(true);
-
-        //If center window is not turned on, you can force JME to
-        //open the window at certain x,y coords.  These are ignored
-        //if the screen is set to "fullscreen".
-        settings.setWindowXPosition(0);
-        settings.setWindowYPosition(0);
-        
-        try
-        {
-           //Let's try and load the AppSetting parameters back into memory
-            InputStream out = new FileInputStream("TestMonitorApp.prefs");
-            settings.load(out);
-        }
-        catch (IOException e)
-        {
-            System.out.println("failed to load settings, reverting to defaults");
-        }
-        app.setSettings(settings);
-
-        app.start();
-    }
-
-    
-    @Override
-    public void simpleInitApp() {
-        flyCam.setDragToRotate(true);
-        int numMonitors = 1;
-
-        //If monitor is define, Jme supports multiple monitors. Setup to keys
-        if (monitors == null) {
-           inputManager.addMapping("down", new KeyTrigger(KeyInput.KEY_DOWN));
-           inputManager.addMapping("fullscreen", new KeyTrigger(KeyInput.KEY_F));
-           inputManager.addListener(this, "down", "fullscreen");
-        }
-
-        //Get the selected monitor
-        monitorSelected = settings.getMonitor();
-        monitors  = context.getMonitors();
-        if (monitors != null)
-           numMonitors = monitors.size();
-        
-
-
-        //Let's define the labels for users to see what is going on with Multiple Monitor
-        String labelValue = "";
-        labelValue = "There are "+numMonitors+" monitor(s) hooked up to this computer.";
-        txt = new BitmapText(loadGuiFont());
-        txt.setText(labelValue);
-        txt.setLocalTranslation(0, settings.getHeight(), 0);
-        guiNode.attachChild(txt);
-
-        txt = new BitmapText(loadGuiFont());
-        if (!settings.isFullscreen())
-           txt.setText("Window is on Monitor N/A (fullscreen only feature)");
-        else
-           txt.setText("Window is on Monitor "+settings.getMonitor());
-           
-        txt.setLocalTranslation(0, settings.getHeight() - 40, 0);
-        guiNode.attachChild(txt);
-
-        if (monitors != null) {
-           selectedMonitorTxt  = new BitmapText(loadGuiFont());
-           //Lets display information about selected monitor
-           String label = "Selected Monitor "+ 
-                    "Name: "+monitors.get(settings.getMonitor()).name+" "+
-                    monitorSelected+ " Res: " + 
-                    monitors.get(settings.getMonitor()).width+","+
-                    monitors.get(settings.getMonitor()).height +
-                    " refresh: "+monitors.get(settings.getMonitor()).rate;
-           selectedMonitorTxt.setText(label);
-           selectedMonitorTxt.setLocalTranslation(0, settings.getHeight() - 80, 0);
-           guiNode.attachChild(selectedMonitorTxt);
-
-           //Let's loop through all the monitors and display on the screen
-           for(int i = 0; i < monitors.size(); i++) {
-              MonitorInfo monitor = monitors.get(i);
-              labelValue = "Mon : "+i+" "+monitor.name+" " + monitor.width +","+ monitor.height +" refresh: "+ monitor.rate;
-              txt = new BitmapText(loadGuiFont());
-              txt.setText(labelValue);
-              txt.setLocalTranslation(0, settings.getHeight() - 160 - (40*i), 0);
-              guiNode.attachChild(txt);
-           }
-        }
-
-        //Lets put a label up there for FullScreen/Window toggle
-        fullScreenTxt = new BitmapText(loadGuiFont());
-        if (!settings.isFullscreen())
-           fullScreenTxt.setText("(f) Window Screen");
-        else
-           fullScreenTxt.setText("(f) Fullscreen");
-           
-        fullScreenTxt.setLocalTranslation(00, settings.getHeight() - 240, 0);
-        guiNode.attachChild(fullScreenTxt);
-
-        BitmapText infoTxt = new BitmapText(loadGuiFont());
-        infoTxt.setText("Restart is required to activate changes in settings.");
-        infoTxt.setLocalTranslation(0, settings.getHeight() - 300, 0);
-        guiNode.attachChild(infoTxt);
-
-        
-    }
-
-    @Override
-     public void onAction(String name, boolean isPressed, float tpf) {
+public class TestMonitorApp extends SimpleApplication
+         implements ActionListener {
+
+   private BitmapText txt;
+   private BitmapText selectedMonitorTxt;
+   private BitmapText fullScreenTxt;
+   private int monitorSelected = 0;
+   private Monitors monitors = null;
+
+   public static void main(String[] args) {
+      TestMonitorApp app = new TestMonitorApp();
+      AppSettings settings = new AppSettings(true);
+      settings.setResizable(false);
+      app.setShowSettings(true);
+      settings.setRenderer(AppSettings.LWJGL_OPENGL33);
+      settings.setMonitor(0);
+      settings.setResolution(800, 600);
+
+      settings.setFullscreen(true);
+
+      // Force JME to center the window, this only applies if it is
+      // not fullscreen.
+      settings.setCenterWindow(true);
+
+      // If center window is not turned on, you can force JME to
+      // open the window at certain x,y coords. These are ignored
+      // if the screen is set to "fullscreen".
+      settings.setWindowXPosition(0);
+      settings.setWindowYPosition(0);
+
+      try {
+         // Let's try and load the AppSetting parameters back into memory
+         InputStream out = new FileInputStream("TestMonitorApp.prefs");
+         settings.load(out);
+      } catch (IOException e) {
+         System.out.println("failed to load settings, reverting to defaults");
+      }
+      app.setSettings(settings);
+
+      app.start();
+   }
+
+   @Override
+   public void simpleInitApp() {
+      flyCam.setDragToRotate(true);
+      int numMonitors = 1;
+
+      // If monitor is define, Jme supports multiple monitors. Setup to keys
+      if (monitors == null) {
+         inputManager.addMapping("down", new KeyTrigger(KeyInput.KEY_DOWN));
+         inputManager.addMapping("fullscreen", new KeyTrigger(KeyInput.KEY_F));
+         inputManager.addListener(this, "down", "fullscreen");
+      }
+
+      // Get the selected monitor
+      monitorSelected = settings.getMonitor();
+      monitors = context.getMonitors();
+      if (monitors != null)
+         numMonitors = monitors.size();
+
+      // Let's define the labels for users to see what is going on with Multiple
+      // Monitor
+      String labelValue = "";
+      labelValue = "There are " + numMonitors
+               + " monitor(s) hooked up to this computer.";
+      txt = new BitmapText(loadGuiFont());
+      txt.setText(labelValue);
+      txt.setLocalTranslation(0, settings.getHeight(), 0);
+      guiNode.attachChild(txt);
+
+      txt = new BitmapText(loadGuiFont());
+      if (!settings.isFullscreen())
+         txt.setText("Window is on Monitor N/A (fullscreen only feature)");
+      else
+         txt.setText("Window is on Monitor " + settings.getMonitor());
+
+      txt.setLocalTranslation(0, settings.getHeight() - 40, 0);
+      guiNode.attachChild(txt);
+
+      if (monitors != null) {
+         selectedMonitorTxt = new BitmapText(loadGuiFont());
+         // Lets display information about selected monitor
+         String label = "Selected Monitor " + "Name: "
+                  + monitors.get(settings.getMonitor()).name + " "
+                  + monitorSelected + " Res: "
+                  + monitors.get(settings.getMonitor()).width + ","
+                  + monitors.get(settings.getMonitor()).height + " refresh: "
+                  + monitors.get(settings.getMonitor()).rate;
+         selectedMonitorTxt.setText(label);
+         selectedMonitorTxt.setLocalTranslation(0, settings.getHeight() - 80,
+                  0);
+         guiNode.attachChild(selectedMonitorTxt);
+
+         // Let's loop through all the monitors and display on the screen
+         for (int i = 0; i < monitors.size(); i++) {
+            MonitorInfo monitor = monitors.get(i);
+            labelValue = "Mon : " + i + " " + monitor.name + " " + monitor.width
+                     + "," + monitor.height + " refresh: " + monitor.rate;
+            txt = new BitmapText(loadGuiFont());
+            txt.setText(labelValue);
+            txt.setLocalTranslation(0, settings.getHeight() - 160 - (40 * i),
+                     0);
+            guiNode.attachChild(txt);
+         }
+      }
+
+      // Lets put a label up there for FullScreen/Window toggle
+      fullScreenTxt = new BitmapText(loadGuiFont());
+      if (!settings.isFullscreen())
+         fullScreenTxt.setText("(f) Window Screen");
+      else
+         fullScreenTxt.setText("(f) Fullscreen");
+
+      fullScreenTxt.setLocalTranslation(00, settings.getHeight() - 240, 0);
+      guiNode.attachChild(fullScreenTxt);
+
+      BitmapText infoTxt = new BitmapText(loadGuiFont());
+      infoTxt.setText("Restart is required to activate changes in settings.");
+      infoTxt.setLocalTranslation(0, settings.getHeight() - 300, 0);
+      guiNode.attachChild(infoTxt);
+
+   }
+
+   @Override
+   public void onAction(String name, boolean isPressed, float tpf) {
 
       if (monitors == null)
          return;
-      
+
       if (name.equals("down") && isPressed) {
          monitorSelected++;
          if (monitorSelected >= monitors.size())
             monitorSelected = 0;
          saveSettings();
-      }
-      else if (name.equals("up") && isPressed) {
+      } else if (name.equals("up") && isPressed) {
          monitorSelected--;
          if (monitorSelected < 0)
-            monitorSelected = monitors.size()-1;
+            monitorSelected = monitors.size() - 1;
          saveSettings();
-      }
-      else if (name.equals("fullscreen") && isPressed) {
+      } else if (name.equals("fullscreen") && isPressed) {
          settings.setFullscreen(!settings.isFullscreen());
          saveSettings();
-      }     
+      }
    }
-   
-    /**
-     *  This function saves out the AppSettings into a file to be loaded back in
-     *  on start of application.
-     */
-   public void saveSettings()
-   {
-      
-       try
-       {
-          settings.setMonitor(monitorSelected);
-          OutputStream out = new FileOutputStream("TestMonitorApp.prefs");
-          settings.save(out);
-          
-          int monitorSelected = settings.getMonitor();
-          String label = "Selected Monitor "+ monitorSelected+
-                   " "+ monitors.get(monitorSelected).name+
-                   " Res: " +monitors.get(monitorSelected).width+","+
-                   monitors.get(monitorSelected).height +
-                   "refresh: "+monitors.get(monitorSelected).rate;
-          selectedMonitorTxt.setText(label);
-          if (!settings.isFullscreen())
-             fullScreenTxt.setText("(f) Window Screen");
-          else
-             fullScreenTxt.setText("(f) Fullscreen");
-       }
-       catch (FileNotFoundException e)
-       {
-           // TODO Auto-generated catch block
-           e.printStackTrace();
-       }
-       catch (IOException e)
-       {
-           // TODO Auto-generated catch block
-           e.printStackTrace();
-       }
 
-   }
+   /**
+    * This function saves out the AppSettings into a file to be loaded back in
+    * on start of application.
+    */
+   public void saveSettings() {
+
+      try {
+         settings.setMonitor(monitorSelected);
+         OutputStream out = new FileOutputStream("TestMonitorApp.prefs");
+         settings.save(out);
+
+         int monitorSelected = settings.getMonitor();
+         String label = "Selected Monitor " + monitorSelected + " "
+                  + monitors.get(monitorSelected).name + " Res: "
+                  + monitors.get(monitorSelected).width + ","
+                  + monitors.get(monitorSelected).height + "refresh: "
+                  + monitors.get(monitorSelected).rate;
+         selectedMonitorTxt.setText(label);
+         if (!settings.isFullscreen())
+            fullScreenTxt.setText("(f) Window Screen");
+         else
+            fullScreenTxt.setText("(f) Fullscreen");
+      } catch (FileNotFoundException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IOException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
 
+   }
 
 }

+ 11 - 13
jme3-ios/src/main/java/com/jme3/system/ios/IGLESContext.java

@@ -268,17 +268,15 @@ public class IGLESContext implements JmeContext {
         throw new UnsupportedOperationException("not implemented yet");
     }
 
-	@Override
-	public Monitors getMonitors()
-	{
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public int getPrimaryMonitor()
-	{
-		// TODO Auto-generated method stub
-		return 0;
-	}
+    @Override
+    public Monitors getMonitors() {
+      // TODO Auto-generated method stub
+      return null;
+    }
+
+    @Override
+    public int getPrimaryMonitor() {
+      // TODO Auto-generated method stub
+      return 0;
+    }
 }

+ 429 - 452
jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java

@@ -1,33 +1,27 @@
 /*
- * Copyright (c) 2009-2021 jMonkeyEngine
- * All rights reserved.
+ * Copyright (c) 2009-2021 jMonkeyEngine All rights reserved.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * Redistribution and use in source and binary forms, with or without modification, are permitted
+ * provided that the following conditions are met:
  *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions
+ * and the following disclaimer.
  *
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials provided with
+ * the distribution.
  *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors may be used to endorse or
+ * promote products derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 package com.jme3.system.lwjgl;
@@ -51,470 +45,453 @@ import org.lwjgl.opengl.PixelFormat;
 
 public class LwjglCanvas extends LwjglAbstractDisplay implements JmeCanvasContext {
 
-    protected static final int TASK_NOTHING = 0,
-                               TASK_DESTROY_DISPLAY = 1,
-                               TASK_CREATE_DISPLAY = 2,
-                               TASK_COMPLETE = 3;
-    
-//    protected static final boolean USE_SHARED_CONTEXT =
-//                Boolean.parseBoolean(System.getProperty("jme3.canvas.sharedctx", "true"));
-    
-    protected static final boolean USE_SHARED_CONTEXT = false;
-    
-    private static final Logger logger = Logger.getLogger(LwjglDisplay.class.getName());
-    private Canvas canvas;
-    private int width;
-    private int height;
-
-    private final Object taskLock = new Object();
-    private int desiredTask = TASK_NOTHING;
-
-    private Thread renderThread;
-    private boolean runningFirstTime = true;
-    private boolean mouseWasGrabbed = false;
-    
-    private boolean mouseWasCreated = false;
-    private boolean keyboardWasCreated = false;
-
-    private Pbuffer pbuffer;
-    private PixelFormat pbufferFormat;
-    private PixelFormat canvasFormat;
-
-    private class GLCanvas extends Canvas {
-        @Override
-        public void addNotify(){
-            super.addNotify();
-
-            if (renderThread != null && renderThread.getState() == Thread.State.TERMINATED) {
-                return; // already destroyed.
-            }
-
-            if (renderThread == null){
-                logger.log(Level.FINE, "EDT: Creating OGL thread.");
-
-                // Also set some settings on the canvas here.
-                // So we don't do it outside the AWT thread.
-                canvas.setFocusable(true);
-                canvas.setIgnoreRepaint(true);
-
-                renderThread = new Thread(LwjglCanvas.this, THREAD_NAME);
-                renderThread.start();
-            }else if (needClose.get()){
-                return;
-            }
-
-            logger.log(Level.FINE, "EDT: Telling OGL to create display ..");
-            synchronized (taskLock){
-                desiredTask = TASK_CREATE_DISPLAY;
-//                while (desiredTask != TASK_COMPLETE){
-//                    try {
-//                        taskLock.wait();
-//                    } catch (InterruptedException ex) {
-//                        return;
-//                    }
-//                }
-//                desiredTask = TASK_NOTHING;
-            }
-//            logger.log(Level.FINE, "EDT: OGL has created the display");
-        }
+  protected static final int TASK_NOTHING = 0, TASK_DESTROY_DISPLAY = 1, TASK_CREATE_DISPLAY = 2,
+      TASK_COMPLETE = 3;
 
-        @Override
-        public void removeNotify(){
-            if (needClose.get()){
-                logger.log(Level.FINE, "EDT: Application is stopped. Not restoring canvas.");
-                super.removeNotify();
-                return;
-            }
-
-            // We must tell GL context to shut down and wait for it to
-            // shut down. Otherwise, issues will occur.
-            logger.log(Level.FINE, "EDT: Telling OGL to destroy display ..");
-            synchronized (taskLock){
-                desiredTask = TASK_DESTROY_DISPLAY;
-                while (desiredTask != TASK_COMPLETE){
-                    try {
-                        taskLock.wait();
-                    } catch (InterruptedException ex){
-                        super.removeNotify();
-                        return;
-                    }
-                }
-                desiredTask = TASK_NOTHING;
-            }
-            
-            logger.log(Level.FINE, "EDT: Acknowledged receipt of canvas death");
-            // GL context is dead at this point
+  // protected static final boolean USE_SHARED_CONTEXT =
+  // Boolean.parseBoolean(System.getProperty("jme3.canvas.sharedctx", "true"));
 
-            super.removeNotify();
-        }
-    }
+  protected static final boolean USE_SHARED_CONTEXT = false;
 
-    public LwjglCanvas(){
-        super();
-        canvas = new GLCanvas();
-    }
+  private static final Logger logger = Logger.getLogger(LwjglDisplay.class.getName());
+  private Canvas canvas;
+  private int width;
+  private int height;
 
-    @Override
-    public Type getType() {
-        return Type.Canvas;
-    }
+  private final Object taskLock = new Object();
+  private int desiredTask = TASK_NOTHING;
 
-    @Override
-    public void create(boolean waitFor){
-        if (renderThread == null){
-            logger.log(Level.FINE, "MAIN: Creating OGL thread.");
+  private Thread renderThread;
+  private boolean runningFirstTime = true;
+  private boolean mouseWasGrabbed = false;
 
-            renderThread = new Thread(LwjglCanvas.this, THREAD_NAME);
-            renderThread.start();
-        }
-        // do not do anything.
-        // superclass's create() will be called at initInThread()
-        if (waitFor) {
-            waitFor(true);
-        }
-    }
+  private boolean mouseWasCreated = false;
+  private boolean keyboardWasCreated = false;
+
+  private Pbuffer pbuffer;
+  private PixelFormat pbufferFormat;
+  private PixelFormat canvasFormat;
 
+  private class GLCanvas extends Canvas {
     @Override
-    public void setTitle(String title) {
+    public void addNotify() {
+      super.addNotify();
+
+      if (renderThread != null && renderThread.getState() == Thread.State.TERMINATED) {
+        return; // already destroyed.
+      }
+
+      if (renderThread == null) {
+        logger.log(Level.FINE, "EDT: Creating OGL thread.");
+
+        // Also set some settings on the canvas here.
+        // So we don't do it outside the AWT thread.
+        canvas.setFocusable(true);
+        canvas.setIgnoreRepaint(true);
+
+        renderThread = new Thread(LwjglCanvas.this, THREAD_NAME);
+        renderThread.start();
+      } else if (needClose.get()) {
+        return;
+      }
+
+      logger.log(Level.FINE, "EDT: Telling OGL to create display ..");
+      synchronized (taskLock) {
+        desiredTask = TASK_CREATE_DISPLAY;
+        // while (desiredTask != TASK_COMPLETE){
+        // try {
+        // taskLock.wait();
+        // } catch (InterruptedException ex) {
+        // return;
+        // }
+        // }
+        // desiredTask = TASK_NOTHING;
+      }
+      // logger.log(Level.FINE, "EDT: OGL has created the display");
     }
 
     @Override
-    public void restart() {
-        frameRate = settings.getFrameRate();
-        // TODO: Handle other cases, like change of pixel format, etc.
+    public void removeNotify() {
+      if (needClose.get()) {
+        logger.log(Level.FINE, "EDT: Application is stopped. Not restoring canvas.");
+        super.removeNotify();
+        return;
+      }
+
+      // We must tell GL context to shut down and wait for it to
+      // shut down. Otherwise, issues will occur.
+      logger.log(Level.FINE, "EDT: Telling OGL to destroy display ..");
+      synchronized (taskLock) {
+        desiredTask = TASK_DESTROY_DISPLAY;
+        while (desiredTask != TASK_COMPLETE) {
+          try {
+            taskLock.wait();
+          } catch (InterruptedException ex) {
+            super.removeNotify();
+            return;
+          }
+        }
+        desiredTask = TASK_NOTHING;
+      }
+
+      logger.log(Level.FINE, "EDT: Acknowledged receipt of canvas death");
+      // GL context is dead at this point
+
+      super.removeNotify();
     }
+  }
 
-    @Override
-    public Canvas getCanvas(){
-        return canvas;
+  public LwjglCanvas() {
+    super();
+    canvas = new GLCanvas();
+  }
+
+  @Override
+  public Type getType() {
+    return Type.Canvas;
+  }
+
+  @Override
+  public void create(boolean waitFor) {
+    if (renderThread == null) {
+      logger.log(Level.FINE, "MAIN: Creating OGL thread.");
+
+      renderThread = new Thread(LwjglCanvas.this, THREAD_NAME);
+      renderThread.start();
     }
-    
-    @Override
-    protected void runLoop(){
-        if (desiredTask != TASK_NOTHING){
-            synchronized (taskLock){
-                switch (desiredTask){
-                    case TASK_CREATE_DISPLAY:
-                        logger.log(Level.FINE, "OGL: Creating display ..");
-                        restoreCanvas();
-                        listener.gainFocus();
-                        desiredTask = TASK_NOTHING;
-                        break;
-                    case TASK_DESTROY_DISPLAY:
-                        logger.log(Level.FINE, "OGL: Destroying display ..");
-                        listener.loseFocus();
-                        pauseCanvas();
-                        break;
-                }
-                desiredTask = TASK_COMPLETE;
-                taskLock.notifyAll();
-            }
-        }
-        
-        if (renderable.get()){
-            int newWidth = Math.max(canvas.getWidth(), 1);
-            int newHeight = Math.max(canvas.getHeight(), 1);
-            if (width != newWidth || height != newHeight){
-                width = newWidth;
-                height = newHeight;
-                if (listener != null){
-                    listener.reshape(width, height);
-                }
-            }
-        }else{
-            if (frameRate <= 0){
-                // NOTE: MUST be done otherwise 
-                // Windows OS will freeze
-                Display.sync(30);
-            }
+    // do not do anything.
+    // superclass's create() will be called at initInThread()
+    if (waitFor) {
+      waitFor(true);
+    }
+  }
+
+  @Override
+  public void setTitle(String title) {}
+
+  @Override
+  public void restart() {
+    frameRate = settings.getFrameRate();
+    // TODO: Handle other cases, like change of pixel format, etc.
+  }
+
+  @Override
+  public Canvas getCanvas() {
+    return canvas;
+  }
+
+  @Override
+  protected void runLoop() {
+    if (desiredTask != TASK_NOTHING) {
+      synchronized (taskLock) {
+        switch (desiredTask) {
+          case TASK_CREATE_DISPLAY:
+            logger.log(Level.FINE, "OGL: Creating display ..");
+            restoreCanvas();
+            listener.gainFocus();
+            desiredTask = TASK_NOTHING;
+            break;
+          case TASK_DESTROY_DISPLAY:
+            logger.log(Level.FINE, "OGL: Destroying display ..");
+            listener.loseFocus();
+            pauseCanvas();
+            break;
         }
-        
-        super.runLoop();
+        desiredTask = TASK_COMPLETE;
+        taskLock.notifyAll();
+      }
     }
 
-    private void pauseCanvas(){
-        if (Mouse.isCreated()){
-            if (Mouse.isGrabbed()){
-                Mouse.setGrabbed(false);
-                mouseWasGrabbed = true;
-            }
-            mouseWasCreated = true;
-            Mouse.destroy();
-        }
-        if (Keyboard.isCreated()){
-            keyboardWasCreated = true;
-            Keyboard.destroy();
+    if (renderable.get()) {
+      int newWidth = Math.max(canvas.getWidth(), 1);
+      int newHeight = Math.max(canvas.getHeight(), 1);
+      if (width != newWidth || height != newHeight) {
+        width = newWidth;
+        height = newHeight;
+        if (listener != null) {
+          listener.reshape(width, height);
         }
+      }
+    } else {
+      if (frameRate <= 0) {
+        // NOTE: MUST be done otherwise
+        // Windows OS will freeze
+        Display.sync(30);
+      }
+    }
+
+    super.runLoop();
+  }
+
+  private void pauseCanvas() {
+    if (Mouse.isCreated()) {
+      if (Mouse.isGrabbed()) {
+        Mouse.setGrabbed(false);
+        mouseWasGrabbed = true;
+      }
+      mouseWasCreated = true;
+      Mouse.destroy();
+    }
+    if (Keyboard.isCreated()) {
+      keyboardWasCreated = true;
+      Keyboard.destroy();
+    }
 
-        renderable.set(false);
-        destroyContext();
+    renderable.set(false);
+    destroyContext();
+  }
+
+  /**
+   * Called to restore the canvas.
+   */
+  private void restoreCanvas() {
+    logger.log(Level.FINE, "OGL: Waiting for canvas to become displayable..");
+    while (!canvas.isDisplayable()) {
+      try {
+        Thread.sleep(10);
+      } catch (InterruptedException ex) {
+        logger.log(Level.SEVERE, "OGL: Interrupted! ", ex);
+      }
     }
 
-    /**
-     * Called to restore the canvas.
-     */
-    private void restoreCanvas(){
-        logger.log(Level.FINE, "OGL: Waiting for canvas to become displayable..");
-        while (!canvas.isDisplayable()){
-            try {
-                Thread.sleep(10);
-            } catch (InterruptedException ex) {
-                logger.log(Level.SEVERE, "OGL: Interrupted! ", ex);
-            }
-        }
-        
-        logger.log(Level.FINE, "OGL: Creating display context ..");
+    logger.log(Level.FINE, "OGL: Creating display context ..");
 
-        // Set renderable to true, since canvas is now displayable.
-        renderable.set(true);
-        createContext(settings);
+    // Set renderable to true, since canvas is now displayable.
+    renderable.set(true);
+    createContext(settings);
 
-        logger.log(Level.FINE, "OGL: Display is active!");
+    logger.log(Level.FINE, "OGL: Display is active!");
 
-        try {
-            if (mouseWasCreated){
-                Mouse.create();
-                if (mouseWasGrabbed){
-                    Mouse.setGrabbed(true);
-                    mouseWasGrabbed = false;
-                }
-            }
-            if (keyboardWasCreated){
-                Keyboard.create();
-                keyboardWasCreated = false;
-            }
-        } catch (LWJGLException ex){
-            logger.log(Level.SEVERE, "Encountered exception when restoring input", ex);
+    try {
+      if (mouseWasCreated) {
+        Mouse.create();
+        if (mouseWasGrabbed) {
+          Mouse.setGrabbed(true);
+          mouseWasGrabbed = false;
         }
+      }
+      if (keyboardWasCreated) {
+        Keyboard.create();
+        keyboardWasCreated = false;
+      }
+    } catch (LWJGLException ex) {
+      logger.log(Level.SEVERE, "Encountered exception when restoring input", ex);
+    }
 
-        SwingUtilities.invokeLater(new Runnable(){
-            @Override
-            public void run(){
-                canvas.requestFocus();
-            }
-        });
+    SwingUtilities.invokeLater(new Runnable() {
+      @Override
+      public void run() {
+        canvas.requestFocus();
+      }
+    });
+  }
+
+  /**
+   * It seems it is best to use one pixel format for all shared contexts.
+   * 
+   * @see <a href=
+   *      "http://developer.apple.com/library/mac/#qa/qa1248/_index.html">http://developer.apple.com/library/mac/#qa/qa1248/_index.html</a>
+   * 
+   * @param forPbuffer true&rarr;zero samples, false&rarr;correct number of samples
+   * @return a new instance
+   */
+  protected PixelFormat acquirePixelFormat(boolean forPbuffer) {
+    if (forPbuffer) {
+      // Use 0 samples for pbuffer format, prevents
+      // crashes on bad drivers
+      if (pbufferFormat == null) {
+        pbufferFormat = new PixelFormat(settings.getBitsPerPixel(), settings.getAlphaBits(),
+            settings.getDepthBits(), settings.getStencilBits(), 0, // samples
+            0, 0, 0, settings.useStereo3D());
+      }
+      return pbufferFormat;
+    } else {
+      if (canvasFormat == null) {
+        int samples = getNumSamplesToUse();
+        canvasFormat = new PixelFormat(settings.getBitsPerPixel(), settings.getAlphaBits(),
+            settings.getDepthBits(), settings.getStencilBits(), samples, 0, 0, 0,
+            settings.useStereo3D());
+      }
+      return canvasFormat;
     }
-    
-    /**
-     * It seems it is best to use one pixel format for all shared contexts.
-     * @see <a href="http://developer.apple.com/library/mac/#qa/qa1248/_index.html">http://developer.apple.com/library/mac/#qa/qa1248/_index.html</a>
-     * 
-     * @param forPbuffer true&rarr;zero samples, false&rarr;correct number of samples
-     * @return a new instance
-     */
-    protected PixelFormat acquirePixelFormat(boolean forPbuffer){
-        if (forPbuffer){
-            // Use 0 samples for pbuffer format, prevents
-            // crashes on bad drivers
-            if (pbufferFormat == null){
-                pbufferFormat = new PixelFormat(settings.getBitsPerPixel(),
-                                                settings.getAlphaBits(),
-                                                settings.getDepthBits(),
-                                                settings.getStencilBits(),
-                                                0, // samples
-                                                0,
-                                                0, 
-                                                0, 
-                                                settings.useStereo3D());
-            }
-            return pbufferFormat;
-        }else{
-            if (canvasFormat == null){
-                int samples = getNumSamplesToUse();
-                canvasFormat = new PixelFormat(settings.getBitsPerPixel(),
-                                               settings.getAlphaBits(),
-                                               settings.getDepthBits(),
-                                               settings.getStencilBits(),
-                                               samples,
-                                               0,
-                                               0, 
-                                               0, 
-                                               settings.useStereo3D());
-            }
-            return canvasFormat;
-        }
+  }
+
+  /**
+   * Makes sure the pbuffer is available and ready for use
+   * 
+   * @throws LWJGLException if the buffer can't be made current
+   */
+  protected void makePbufferAvailable() throws LWJGLException {
+    if (pbuffer != null && pbuffer.isBufferLost()) {
+      logger.log(Level.WARNING, "PBuffer was lost!");
+      pbuffer.destroy();
+      pbuffer = null;
     }
 
-    /**
-     * Makes sure the pbuffer is available and ready for use
-     * 
-     * @throws LWJGLException if the buffer can't be made current
-     */
-    protected void makePbufferAvailable() throws LWJGLException{
-        if (pbuffer != null && pbuffer.isBufferLost()){
-            logger.log(Level.WARNING, "PBuffer was lost!");
-            pbuffer.destroy();
-            pbuffer = null;
-        }
-        
-        if (pbuffer == null) {
-            pbuffer = new Pbuffer(1, 1, acquirePixelFormat(true), null);
-            pbuffer.makeCurrent();
-            logger.log(Level.FINE, "OGL: Pbuffer has been created");
-            
-            // Any created objects are no longer valid
-            if (!runningFirstTime){
-                renderer.resetGLObjects();
-            }
+    if (pbuffer == null) {
+      pbuffer = new Pbuffer(1, 1, acquirePixelFormat(true), null);
+      pbuffer.makeCurrent();
+      logger.log(Level.FINE, "OGL: Pbuffer has been created");
+
+      // Any created objects are no longer valid
+      if (!runningFirstTime) {
+        renderer.resetGLObjects();
+      }
+    }
+
+    pbuffer.makeCurrent();
+    if (!pbuffer.isCurrent()) {
+      throw new LWJGLException("Pbuffer cannot be made current");
+    }
+  }
+
+  protected void destroyPbuffer() {
+    if (pbuffer != null) {
+      if (!pbuffer.isBufferLost()) {
+        pbuffer.destroy();
+      }
+      pbuffer = null;
+    }
+  }
+
+  /**
+   * This is called: 1) When the context thread ends 2) Any time the canvas becomes non-displayable
+   */
+  @Override
+  protected void destroyContext() {
+    try {
+      // invalidate the state so renderer can resume operation
+      if (!USE_SHARED_CONTEXT) {
+        renderer.cleanup();
+      }
+
+      if (Display.isCreated()) {
+        /*
+         * FIXES: org.lwjgl.LWJGLException: X Error BadWindow (invalid Window parameter)
+         * request_code: 2 minor_code: 0
+         * 
+         * Destroying keyboard early prevents the error above, triggered by destroying keyboard in
+         * by Display.destroy() or Display.setParent(null). Therefore, Keyboard.destroy() should
+         * precede any of these calls.
+         */
+        if (Keyboard.isCreated()) {
+          // Should only happen if called in
+          // LwjglAbstractDisplay.deinitInThread().
+          Keyboard.destroy();
         }
-        
-        pbuffer.makeCurrent();
-        if (!pbuffer.isCurrent()){
-            throw new LWJGLException("Pbuffer cannot be made current");
+
+        // try {
+        // NOTE: On Windows XP, not calling setParent(null)
+        // freezes the application.
+        // On Mac it freezes the application.
+        // On Linux it fixes a crash with X Window System.
+        if (JmeSystem.getPlatform() == Platform.Windows32
+            || JmeSystem.getPlatform() == Platform.Windows64) {
+          // Display.setParent(null);
         }
+        // } catch (LWJGLException ex) {
+        // logger.log(Level.SEVERE, "Encountered exception when setting parent to null", ex);
+        // }
+
+        Display.destroy();
+      }
+
+      // The canvas is no longer visible,
+      // but the context thread is still running.
+      if (!needClose.get()) {
+        // MUST make sure there's still a context current here.
+        // Display is dead, make PBuffer available to the system.
+        makePbufferAvailable();
+
+        renderer.invalidateState();
+      } else {
+        // The context thread is no longer running.
+        // Destroy pbuffer.
+        destroyPbuffer();
+      }
+    } catch (LWJGLException ex) {
+      listener.handleError("Failed make pbuffer available", ex);
     }
-    
-    protected void destroyPbuffer(){
-        if (pbuffer != null){
-            if (!pbuffer.isBufferLost()){
-                pbuffer.destroy();
-            }
-            pbuffer = null;
+  }
+
+  /**
+   * This is called: 1) When the context thread starts 2) Any time the canvas becomes displayable
+   * again. In the first call of this method, OpenGL context is not ready yet. Therefore, OpenCL
+   * context cannot be created. The second call of this method is done after "simpleInitApp" is
+   * called. Therefore, OpenCL won't be available in "simpleInitApp" if Canvas/Swing is used. To use
+   * OpenCL with Canvas/Swing, you need to use OpenCL in the rendering loop "simpleUpdate" and check
+   * for "context.getOpenCLContext()!=null".
+   */
+  @Override
+  protected void createContext(AppSettings settings) {
+    // In case canvas is not visible, we still take framerate
+    // from settings to prevent "100% CPU usage"
+    frameRate = settings.getFrameRate();
+    allowSwapBuffers = settings.isSwapBuffers();
+
+    try {
+      if (renderable.get()) {
+        if (!runningFirstTime) {
+          // because the display is a different opengl context
+          // must reset the context state.
+          if (!USE_SHARED_CONTEXT) {
+            renderer.cleanup();
+          }
         }
-    }
-    
-    /**
-     * This is called:
-     * 1) When the context thread ends
-     * 2) Any time the canvas becomes non-displayable
-     */
-    @Override
-    protected void destroyContext(){
-        try {
-            // invalidate the state so renderer can resume operation
-            if (!USE_SHARED_CONTEXT){
-                renderer.cleanup();
-            }
-            
-            if (Display.isCreated()){
-                /* FIXES:
-                 * org.lwjgl.LWJGLException: X Error
-                 * BadWindow (invalid Window parameter) request_code: 2 minor_code: 0
-                 * 
-                 * Destroying keyboard early prevents the error above, triggered
-                 * by destroying keyboard in by Display.destroy() or Display.setParent(null).
-                 * Therefore, Keyboard.destroy() should precede any of these calls.
-                 */
-                if (Keyboard.isCreated()){
-                    // Should only happen if called in 
-                    // LwjglAbstractDisplay.deinitInThread().
-                    Keyboard.destroy();
-                }
-
-                //try {
-                    // NOTE: On Windows XP, not calling setParent(null)
-                    // freezes the application.
-                    // On Mac it freezes the application.
-                    // On Linux it fixes a crash with X Window System.
-                    if (JmeSystem.getPlatform() == Platform.Windows32
-                     || JmeSystem.getPlatform() == Platform.Windows64){
-                        //Display.setParent(null);
-                    }
-                //} catch (LWJGLException ex) {
-                //    logger.log(Level.SEVERE, "Encountered exception when setting parent to null", ex);
-                //}
-
-                Display.destroy();
-            }
-            
-            // The canvas is no longer visible,
-            // but the context thread is still running.
-            if (!needClose.get()){
-                // MUST make sure there's still a context current here.
-                // Display is dead, make PBuffer available to the system.
-                makePbufferAvailable();
-                
-                renderer.invalidateState();
-            }else{
-                // The context thread is no longer running.
-                // Destroy pbuffer.
-                destroyPbuffer();
-            }
-        } catch (LWJGLException ex) {
-            listener.handleError("Failed make pbuffer available", ex);
+
+        // if the pbuffer is currently active,
+        // make sure to deactivate it
+        destroyPbuffer();
+
+        if (Keyboard.isCreated()) {
+          Keyboard.destroy();
         }
-    }
 
-    /**
-     * This is called:
-     * 1) When the context thread starts
-     * 2) Any time the canvas becomes displayable again.
-	 * In the first call of this method, OpenGL context is not ready yet. Therefore, OpenCL context cannot be created.
-	 * The second call of this method is done after "simpleInitApp" is called. Therefore, OpenCL won't be available in "simpleInitApp" if Canvas/Swing is used.
-	 * To use OpenCL with Canvas/Swing, you need to use OpenCL in the rendering loop "simpleUpdate" and check for "context.getOpenCLContext()!=null".
-     */
-    @Override
-    protected void createContext(AppSettings settings) {
-        // In case canvas is not visible, we still take framerate
-        // from settings to prevent "100% CPU usage"
-        frameRate = settings.getFrameRate();
-        allowSwapBuffers = settings.isSwapBuffers();
-        
         try {
-            if (renderable.get()){
-                if (!runningFirstTime){
-                    // because the display is a different opengl context
-                    // must reset the context state.
-                    if (!USE_SHARED_CONTEXT){
-                        renderer.cleanup();
-                    }
-                }
-                
-                // if the pbuffer is currently active, 
-                // make sure to deactivate it
-                destroyPbuffer();
-                
-                if (Keyboard.isCreated()){
-                    Keyboard.destroy();
-                }
-                
-                try {
-                    Thread.sleep(1000);
-                } catch (InterruptedException ex) {
-                }
-                
-                Display.setVSyncEnabled(settings.isVSync());
-                Display.setParent(canvas);
-                
-                if (USE_SHARED_CONTEXT){
-                    Display.create(acquirePixelFormat(false), pbuffer);
-                }else{
-                    Display.create(acquirePixelFormat(false));
-                }
-				if (settings.isOpenCLSupport()) {
-					initOpenCL();
-				}
-				
-                renderer.invalidateState();
-            }else{
-                // First create the pbuffer, if it is needed.
-                makePbufferAvailable();
-            }
-
-            // At this point, the OpenGL context is active.
-            if (runningFirstTime){
-                // THIS is the part that creates the renderer.
-                // It must always be called, now that we have the pbuffer workaround.
-                initContextFirstTime();
-                runningFirstTime = false;
-            }
-        } catch (LWJGLException ex) {
-            listener.handleError("Failed to initialize OpenGL context", ex);
-            // TODO: Fix deadlock that happens after the error (throw runtime exception?)
+          Thread.sleep(1000);
+        } catch (InterruptedException ex) {
+        }
+
+        Display.setVSyncEnabled(settings.isVSync());
+        Display.setParent(canvas);
+
+        if (USE_SHARED_CONTEXT) {
+          Display.create(acquirePixelFormat(false), pbuffer);
+        } else {
+          Display.create(acquirePixelFormat(false));
+        }
+        if (settings.isOpenCLSupport()) {
+          initOpenCL();
         }
-    }
 
-	@Override
-	public Monitors getMonitors()
-	{
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public int getPrimaryMonitor()
-	{
-		// TODO Auto-generated method stub
-		return 0;
-	}
+        renderer.invalidateState();
+      } else {
+        // First create the pbuffer, if it is needed.
+        makePbufferAvailable();
+      }
+
+      // At this point, the OpenGL context is active.
+      if (runningFirstTime) {
+        // THIS is the part that creates the renderer.
+        // It must always be called, now that we have the pbuffer workaround.
+        initContextFirstTime();
+        runningFirstTime = false;
+      }
+    } catch (LWJGLException ex) {
+      listener.handleError("Failed to initialize OpenGL context", ex);
+      // TODO: Fix deadlock that happens after the error (throw runtime exception?)
+    }
+  }
+
+  @Override
+  public Monitors getMonitors() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public int getPrimaryMonitor() {
+    // TODO Auto-generated method stub
+    return 0;
+  }
 }

+ 10 - 12
jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglDisplay.java

@@ -284,18 +284,16 @@ public class LwjglDisplay extends LwjglAbstractDisplay {
         return ByteBuffer.wrap(imageBuffer);
     }
 
-	@Override
-	public Monitors getMonitors()
-	{
-		// TODO Auto-generated method stub
-		return null;
-	}
+    @Override
+    public Monitors getMonitors() {
+      // TODO Auto-generated method stub
+      return null;
+    }
 
-	@Override
-	public int getPrimaryMonitor()
-	{
-		// TODO Auto-generated method stub
-		return 0;
-	}
+    @Override
+    public int getPrimaryMonitor() {
+      // TODO Auto-generated method stub
+      return 0;
+    }
 
 }

+ 11 - 13
jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglOffscreenBuffer.java

@@ -220,18 +220,16 @@ public class LwjglOffscreenBuffer extends LwjglContext implements Runnable {
     public void setTitle(String title) {
     }
 
-	@Override
-	public Monitors getMonitors()
-	{
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public int getPrimaryMonitor()
-	{
-		// TODO Auto-generated method stub
-		return 0;
-	}
+    @Override
+    public Monitors getMonitors() {
+      // TODO Auto-generated method stub
+      return null;
+    }
+
+    @Override
+    public int getPrimaryMonitor() {
+      // TODO Auto-generated method stub
+      return 0;
+    }
 
 }

+ 12 - 11
jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java

@@ -291,9 +291,9 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
 
 //        long monitor = NULL;
 
-        /** 
-         * Let's grab the monitor selected, if not found it will return primaryMonitor.
-         * if not full screen just use primary monitor data.
+        /**
+         * Let's grab the monitor selected, if not found it will return
+         * primaryMonitor. if not full screen just use primary monitor data.
          */
         if (settings.isFullscreen()) {
            monitor = getMonitor(settings.getMonitor());
@@ -305,18 +305,19 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
         int requestWidth = settings.getWindowWidth();
         int requestHeight = settings.getWindowHeight();
         if (requestWidth <= 0 || requestHeight <= 0) {
-            requestWidth = videoMode.width();
-            requestHeight = videoMode.height();
+           requestWidth = videoMode.width();
+           requestHeight = videoMode.height();
         }
         
-        //Lets use the monitor selected from AppSettings if FullScreen is 
-        //set.
+        // Lets use the monitor selected from AppSettings if FullScreen is
+        // set.
         if (settings.isFullscreen())
-           window = glfwCreateWindow(requestWidth, requestHeight, settings.getTitle(), monitor, NULL);
-        else 
-           window = glfwCreateWindow(requestWidth, requestHeight, settings.getTitle(), NULL, NULL);
+           window = glfwCreateWindow(requestWidth, requestHeight,
+                    settings.getTitle(), monitor, NULL);
+        else
+           window = glfwCreateWindow(requestWidth, requestHeight,
+                    settings.getTitle(), NULL, NULL);
 
-        
         if (window == NULL) {
             throw new RuntimeException("Failed to create the GLFW window");
         }

+ 10 - 12
jme3-vr/src/main/java/com/jme3/system/lwjgl/LwjglDisplayVR.java

@@ -53,17 +53,15 @@ public class LwjglDisplayVR extends LwjglWindowVR {
         return null;
     }
 
-	@Override
-	public Monitors getMonitors()
-	{
-		// TODO Auto-generated method stub
-		return null;
-	}
+    @Override
+    public Monitors getMonitors() {
+      // TODO Auto-generated method stub
+      return null;
+    }
 
-	@Override
-	public int getPrimaryMonitor()
-	{
-		// TODO Auto-generated method stub
-		return 0;
-	}
+    @Override
+    public int getPrimaryMonitor() {
+      // TODO Auto-generated method stub
+      return 0;
+    }
 }