Namek Dev
a developer's log
NamekDev

Regain focus once lost by Java Swing

March 24, 2016

In The Console I primarily use JavaFX for UI. Nonetheless, due to problem with having undecorated taskbar-less always-on-top window I use JFrame from Java Swing to solve it. And here appears a new issue with Swing - how to regain once lost window focus in JFrame?

JFrame contains methods like toFront() or requestFocus(). For me, on Windows 7, calling them separately or one after another doesn’t work. setAutoRequestFocus() doesn’t change a thing. Calling in AWT EventQueue or JavaFX Platform queue to run it in main UI loop didn’t help too. Some sources lead to HKCU\Control Panel\Desktop\ForegroundLockTimeout setting so I tried a timer to defer those calls. Nope.

Finally, I got onto StackOverflow discussion about bringing a window to the front. Tried few solutions but didn’t really work. My last hope was to bind to Windows API functions as I did in some previous projects, so I could mimic a mouse. However (!), in the topic I’ve found there is an old SWT Robot class that enables to do that without messing with C libraries. Which continues to sustain a future hope to support other OS-es than Windows.

Here goes my solution based on Robot class.

First, instantiate Robot - you can do it once.

val robot = new Robot()

And here’s a method that makes my console window visible:

override setVisible(boolean visible) {
    window.visible = visible

    if (visible) {
        EventQueue.invokeLater [
            window.toFront()

            try {
                // remember the last location of mouse
                val oldMouseLocation = MouseInfo.getPointerInfo().getLocation()

                // simulate a mouse click on title bar of window
                robot.mouseMove(window.getX() + 10, window.getY() + 5)
                robot.mousePress(InputEvent.BUTTON1_DOWN_MASK)
                robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK)

                // move mouse to old location
                robot.mouseMove(oldMouseLocation.getX() as int, oldMouseLocation.getY() as int)
            }
            catch (Exception ex) { }
        ]
    }

}

Simply simulate a click on the window and move the mouse cursor back to the original point so user doesn’t notice the hack.

I wonder how it will work on multi-screen environment but probably needs a little of tweaking. For sure: will need some maintenance on slide-in animation.

the-console, java, xtend
comments powered by Disqus