Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NullPointerException thrown in PApplet.dequeueWindowEvents() #918

Open
hx2A opened this issue Jan 16, 2025 · 0 comments
Open

NullPointerException thrown in PApplet.dequeueWindowEvents() #918

hx2A opened this issue Jan 16, 2025 · 0 comments
Assignees

Comments

@hx2A
Copy link
Collaborator

hx2A commented Jan 16, 2025

I had several running Sketches and was moving the windows around when this exception was thrown:

java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because the return value of "java.util.Map.remove(Object)" is null
        at processing.core.PApplet.dequeueWindowEvents(PApplet.java:9740)                                        
        at processing.core.PApplet.handleDraw(PApplet.java:2085)
        at processing.opengl.PSurfaceJOGL$DrawListener.display(PSurfaceJOGL.java:840)                             
        at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:692)
        at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:674)
        at jogamp.opengl.GLAutoDrawableBase$2.run(GLAutoDrawableBase.java:443)                                    
        at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1293)
        at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:1147)
        at com.jogamp.newt.opengl.GLWindow.display(GLWindow.java:782)
        at com.jogamp.opengl.util.AWTAnimatorImpl.display(AWTAnimatorImpl.java:81)
        at com.jogamp.opengl.util.AnimatorBase.display(AnimatorBase.java:453)
        at com.jogamp.opengl.util.FPSAnimator$MainTask.run(FPSAnimator.java:178)
        at java.base/java.util.TimerThread.mainLoop(Timer.java:566) 
        at java.base/java.util.TimerThread.run(Timer.java:516)

I see what the problem is. In the code there is this:

  /**
   * Internal use only: called by Surface objects to queue a position
   * event to call windowPositioned() when it's safe, which is after
   * the beginDraw() call and before the draw(). Note that this is
   * only the notification that the window is in a new position.
   */
  public void postWindowMoved(int newX, int newY) {
    if (external && !fullScreen) {
      frameMoved(newX, newY);
    }

    windowEventQueue.put("x", newX);
    windowEventQueue.put("y", newY);
  }


  /** Called when the window is moved */
  public void windowMoved() {  }


  private void dequeueWindowEvents() {
    if (windowEventQueue.containsKey("x")) {
      windowX = windowEventQueue.remove("x");
      windowY = windowEventQueue.remove("y");    // line 9740, where exception was thrown
      windowMoved();
    }
    if (windowEventQueue.containsKey("w")) {
      // these should already match width/height
      //windowResized(windowEventQueue.remove("w"),
      //              windowEventQueue.remove("h"));
      windowEventQueue.remove("w");
      windowEventQueue.remove("h");
      windowResized();
    }
  }

According to the comment, that postWindowMoved() method gets called by Surface objects "after the beginDraw() call and before the draw()".

That dequeueWindowEvents() method gets called in handleDraw() at a point that is also after the beginDraw() call and before the draw().

Putting both "x" and "y" in windowEventQueue is not an atomic operation, even though the queue is a ConcurrentHashMap, which is thread safe. This must have been a fluke exception where postWindowMoved() and dequeueWindowEvents() were executing at the same time, and "x" was added but "y" had not.

This is a rare exception and is probably next to impossible to reproduce. Nevertheless, it should be an easy thing to fix, so let's fix it, and I'd like to work on it.

My proposed solution is for windowEventQueue to store pairs of numbers, for both x & y, and w & h. We can create a simple dummy class Pair that we put and remove from the queue.

@hx2A hx2A self-assigned this Jan 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant