-
Bug
-
Resolution: Unresolved
-
P3
-
8, 9
-
x86
-
os_x
FULL PRODUCT VERSION :
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Darwin Alans-iMac 14.5.0 Darwin Kernel Version 14.5.0: Tue Sep 1 21:23:09 PDT 2015; root:xnu-2782.50.1~1/RELEASE_X86_64 x86_64
A DESCRIPTION OF THE PROBLEM :
The specification of requestFocus() says:
Requests that this Component get the input focus, and that this Component's top-level ancestor become the focused Window.
Every effort will be made to honor the request; however, in some cases it may be impossible to do so.
On OS X, if the application is not active (the focused window belongs to some other application), requestFocus() fails to make the Window focused. It should try to activate the application, but as far as I can tell, it does not.
The NSWindow makeKeyWindow method is called, but the NSApplication activateIgnoringOtherApps: method is not.
As far as I know, there is no public API that will activate the application.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached program.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The test program should display a Java frame behind the Chess application frame. After a short delay, the test program should become active and the Java frame should be focused. A message should be written that the activation was successful.
ACTUAL -
The Java frame remains behind the Chess application frame and a failure message is written. After another short delay, the Java frame is activated using a private API, and a message to that effect is written.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package test;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import sun.lwawt.macosx.LWCToolkit;
public class Test
{
private JFrame fr;
private Timer t;
private int counter;
public Test()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
fr = new JFrame("Test");
fr.setBounds(100, 100, 400, 300);
fr.setVisible(true);
{
// Make a different application active before we try to reactivate our frame
Runtime r = Runtime.getRuntime();
try {
r.exec("/usr/bin/open /Applications/Chess.app");
Thread.sleep(5000);
} catch (IOException ex) {
System.err.println("Unable to open application: " + ex.getMessage());
} catch (InterruptedException ex) {
return;
}
}
System.err.println("Requesting focus...");
fr.requestFocus();
t = new Timer(200, new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
timerTick();
}
});
t.start();
}
});
}
private void timerTick()
{
if (fr.isActive()) {
t.stop();
System.err.println("Frame successfully activated");
} else {
if (counter == 0) {
System.err.println("Waiting for frame to activate...");
}
if (++counter > 25) {
System.err.println("Frame was not activated... forcing activation");
forceActivation();
}
if (counter > 50) {
t.stop();
System.err.println("Force activation failed!");
}
}
}
private void forceActivation()
{
LWCToolkit lwcToolkit = (LWCToolkit) Toolkit.getDefaultToolkit();
lwcToolkit.activateApplicationIgnoringOtherApps();
}
public static void main(String[] args)
{
new Test();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
The workaround is to use the private API used in the test program.
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Darwin Alans-iMac 14.5.0 Darwin Kernel Version 14.5.0: Tue Sep 1 21:23:09 PDT 2015; root:xnu-2782.50.1~1/RELEASE_X86_64 x86_64
A DESCRIPTION OF THE PROBLEM :
The specification of requestFocus() says:
Requests that this Component get the input focus, and that this Component's top-level ancestor become the focused Window.
Every effort will be made to honor the request; however, in some cases it may be impossible to do so.
On OS X, if the application is not active (the focused window belongs to some other application), requestFocus() fails to make the Window focused. It should try to activate the application, but as far as I can tell, it does not.
The NSWindow makeKeyWindow method is called, but the NSApplication activateIgnoringOtherApps: method is not.
As far as I know, there is no public API that will activate the application.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached program.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The test program should display a Java frame behind the Chess application frame. After a short delay, the test program should become active and the Java frame should be focused. A message should be written that the activation was successful.
ACTUAL -
The Java frame remains behind the Chess application frame and a failure message is written. After another short delay, the Java frame is activated using a private API, and a message to that effect is written.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package test;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import sun.lwawt.macosx.LWCToolkit;
public class Test
{
private JFrame fr;
private Timer t;
private int counter;
public Test()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
fr = new JFrame("Test");
fr.setBounds(100, 100, 400, 300);
fr.setVisible(true);
{
// Make a different application active before we try to reactivate our frame
Runtime r = Runtime.getRuntime();
try {
r.exec("/usr/bin/open /Applications/Chess.app");
Thread.sleep(5000);
} catch (IOException ex) {
System.err.println("Unable to open application: " + ex.getMessage());
} catch (InterruptedException ex) {
return;
}
}
System.err.println("Requesting focus...");
fr.requestFocus();
t = new Timer(200, new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
timerTick();
}
});
t.start();
}
});
}
private void timerTick()
{
if (fr.isActive()) {
t.stop();
System.err.println("Frame successfully activated");
} else {
if (counter == 0) {
System.err.println("Waiting for frame to activate...");
}
if (++counter > 25) {
System.err.println("Frame was not activated... forcing activation");
forceActivation();
}
if (counter > 50) {
t.stop();
System.err.println("Force activation failed!");
}
}
}
private void forceActivation()
{
LWCToolkit lwcToolkit = (LWCToolkit) Toolkit.getDefaultToolkit();
lwcToolkit.activateApplicationIgnoringOtherApps();
}
public static void main(String[] args)
{
new Test();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
The workaround is to use the private API used in the test program.