public void init(ThreadGroup tg, final GLWindow glWindow) { isValid = false; this.glWindow = glWindow; this.glWindow.addWindowListener( new WindowAdapter() { // Closing action: back to parent! @Override public void windowDestroyNotify(WindowEvent e) { if (isValid() && WindowClosingMode.DO_NOTHING_ON_CLOSE == glWindow.getDefaultCloseOperation()) { if (null == glWindow.getParent()) { // we may be called directly by the native EDT new Thread( new Runnable() { @Override public void run() { if (glWindow.isNativeValid()) { glWindow.reparentWindow(awtParent); } } }) .start(); } } } }); glEventListener = createInstance(glEventListenerClazzName); if (null == glEventListener) { return; } try { if (!setField(glEventListener, "window", glWindow)) { setField(glEventListener, "glWindow", glWindow); } glWindow.addGLEventListener(this); glWindow.addGLEventListener(glEventListener); if (glEventListener instanceof WindowListener) { glWindow.addWindowListener((WindowListener) glEventListener); } if (glEventListener instanceof MouseListener) { glWindow.addMouseListener((MouseListener) glEventListener); } if (glEventListener instanceof KeyListener) { glWindow.addKeyListener((KeyListener) glEventListener); } if (!noDefaultKeyListener) { glWindow.addKeyListener(this); } glWindow.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err); // glAnimator = new FPSAnimator(canvas, 60); glAnimator = new Animator(); glAnimator.setModeBits( false, Animator.MODE_EXPECT_AWT_RENDERING_THREAD); // No AWT thread involved! glAnimator.setThreadGroup(tg); glAnimator.add(glWindow); glAnimator.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, null); } catch (Throwable t) { throw new RuntimeException(t); } isValid = true; }