Search code examples
javaswingfocusubuntu-12.04focus-stealing

How to prevent a Java graphical program from stealing focus when updating the window?


On an (embedded) Ubuntu 12.04 system, we have a simple Java program that displays some graphics patterns on a window, updating every second or so. We use it to monitor some processes running on the system. The problem is that while it is active and not minimized, it steals the focus whenever the window is updated. This makes working with the open terminal windows impossible.

The behaviour is the same when running the app form command line or from Eclipse IDE.

The same problem does not occur on Windows 7 when running under NetBeans IDE.

How can we prevent the Java app from stealing the focus on the Ubuntu machine?


UPDATE 1: Found this question that seem to struggle with the same problem: How do I stop/workaround Java apps stealing focus in Linux window managers . Reading it, I learned that the problem is with using JFrame as a container, which is what we use. Their solution was to use the JWindow container instead of JFrame container. However, searching for the difference, the JWindow is "naked" and does not behave like a "real" window, as there's no decorations. Is there a way to use JWindow inside a JFrame, and thus eliminate the focus stealing?


UPDATE 2: Trying to run this program on an Ubuntu Virtual Machine on the PC gives the same misbehaviour. This suggests that there is a difference of the Java runtime of Windows 7 and Linux, and that the problem is not specific to the Embedded linux.


UPDATE 3: Here's a SSCCE:

//package SSCCE;

import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;

public class MonitorSSCCE extends JFrame{

    public static void main(String[] args) 
    {
        // Set the frame
        JFrame ecoreFrame = new JFrame("SSCCE");
        ecoreFrame.setSize(120, 120);
        ecoreFrame.setVisible(true);

        // Refresh frame every 200 msec
        while (true) {
            GRFX grfx = new GRFX();
            ecoreFrame.add(grfx);
            ecoreFrame.setVisible(true);
            grfx = null;

            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {

            }
        }
    }


    static int clr = 0;

    public static class GRFX extends JPanel {

        public void paintComponent(Graphics comp) {
            Graphics2D comp2D = (Graphics2D) comp;

            // Draw a changin color rectangle
            comp2D.setColor(new Color(clr, 0, 0));
            Rectangle2D.Double rect = new Rectangle2D.Double(10, 10, 100, 100);
            comp2D.fill(rect);
            clr = clr + 10;
            if (clr > 255)
                clr = 0;
        }
    }
}

UPDATE 4: While preparing the SSCCE, I had some reading and find out about the plethora of window refresh methods of the JFrame object. It happens that the problem was the setVisible() call inside the while loop. The solution was to replace it with the repaint() method.


Solution

  • Replacing the setVisible() method call inside the while() loop by repaint() eliminated the problem:

        // Refresh frame every 200 msec
        while (true) {
            GRFX grfx = new GRFX();
            ecoreFrame.add(grfx);
            ecoreFrame.repaint();
            grfx = null;
    
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
    
            }
        }