title: Java2D: interaction between XWindows events and frame rate
body: <p>I'm experiencing an unexpected interaction between system events and the window refresh rate in simple Java2D applications on Linux/XWindows. It is best demonstrated with the small example below.</p>
  
  <p>This program creates a small window in which a half-circle is displayed at different rotations. The graphics are updated at 60 frames per second in order to produce a flickering display. This is achieved through a <code>BufferStrategy</code>, namely by calling its <code>show</code> method.</p>
  
  <p>However, I note that when I (a) move the mouse over the window so that the window receives mouse-over events or (b) hold down a key on the keyboard so that the window receives keyboard events, the flickering increases visibly.</p>
  
  <p>As the rate at which <code>BufferStrategy.show()</code> is called is not affected by these events, as can be seen by the print-outs on the console (they should constantly be at around 60 fps). However, the faster flickering indicates that the rate at which the display is <em>actually</em> updated, does indeed change.</p>
  
  <p>It looks to me that <em>actual</em>, i.e., visible 60 frames per second are not achieved unless mouse or keyboard events are generated.</p>
  
  <pre class="lang-java prettyprint-override"><code>public class Test {
      // pass the path to 'test.png' as command line parameter
      public static void main(String[] args) throws Exception {
          BufferedImage image = ImageIO.read(new File(args[0]));
  
          // create window
          JFrame frame = new JFrame();
          Canvas canvas = new Canvas();
          canvas.setPreferredSize(new Dimension(100, 100));
          frame.getContentPane().add(canvas);
          frame.pack();
          frame.setVisible(true);
  
          int fps = 0;
          long nsPerFrame = 1000000000 / 60; // 60 = target fps
          long showTime = System.nanoTime() + nsPerFrame;
          long printTime = System.currentTimeMillis() + 1000;
          for (int tick = 0; true; tick++) {
              BufferStrategy bs = canvas.getBufferStrategy();
              if (bs == null) {
                  canvas.createBufferStrategy(2);
                  continue;
              }
  
              // draw frame
              Graphics g = bs.getDrawGraphics();
              int framex = (tick % 4) * 64;
              g.drawImage(image, 18, 18, 82, 82, framex, 0, framex+64, 64, null);
              g.dispose();
              bs.show();
  
              // enforce frame rate
              long sleepTime = showTime - System.nanoTime();
              if (sleepTime &gt; 0) {
                  long sleepMillis = sleepTime / 1000000;
                  int sleepNanos = (int) (sleepTime - (sleepMillis * 1000000));
                  try {
                      Thread.sleep(sleepMillis, sleepNanos);
                  } catch (InterruptedException ie) {
                      /* ignore */
                  }
              }
              showTime += nsPerFrame;
  
              // print frame rate achieved
              fps++;
              if (System.currentTimeMillis() &gt; printTime) {
                  System.out.println("fps: " + fps);
                  fps = 0;
                  printTime += 1000;
              }
          }
      }
  }
  </code></pre>
  
  <p>A sample image to use with this program (the path to which must be passed as a command line argument) is this:</p>
  
  <p><a href="https://i.stack.imgur.com/dGtdx.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/dGtdx.png" alt="enter image description here"></a></p>
  
  <p>So my (2-part) question is:</p>
  
  <p><strong>Why is this effect happening? How can I reach <em>actual</em> 60 fps?</strong></p>
  
  <p><em>(Bonus question for commenters: do you experience the same effect also under other operating systems?)</em></p>