1

EDIT 1/16/2013: The original question has been deleted. This seems to be a bug with the JDK 7 on mac OSX. I have filed a bug report with Sun (Oracle).

The file below uses the awt class GraphicsEnvironment and the method setFullScreenWindow to display an image to fullscreen. No images are included, so the screen will be gray when running the code. The key bindings should, however, still work.

There are two key bindings. Pressing 'ENTER' should print "Enter was pressed." to stdout. Pressing 'ESCAPE' should print "Program Terminated by ESC Key" to stdout and quit the program.

Using Windows 7 64 and JDK Java SE 6 AND 7 these key bindings work as expected.

Using Mac OSX 10.7 Lion and JDK Java SE 6 these key bindings work as expected.

Using Mac OSX 10.7 Lion and JDK Java SE 7 these key bindings stop working.

Rolling back to JDK Java SE 6 causes them to start working again.

I don't know if it affects other OSs.

I have tried all versions of JComponent.WHEN_IN_FOCUS etc... and none of these options fixes the problem.

Below is an SSCCE that will reproduce the error only if you are using Mac OSX 10.7 and JDK Java SE 7.

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

public class FullScreen extends JFrame
{
    /*
     * screenImage is never set in this code. It can be set to any image
     * the error will still be present. Images have been omitted to simplify
     * the example case.
     */
    private Image screenImage;
    private int width;
    private int height;

    //Create panel for displaying images using paintComponent()
    private PaintPanel mainImagePanel;

    //Used for keybinding
    private Action enterAction;
    private Action escapeAction;
    private static final String enter = "ENTER";
    private static final String escape = "ESCAPE";

    public FullScreen()
    {
 /**********************************************
  ******THE BELOW LINES CAUSE THE ERROR*********
  **********************************************/

        /****************************************** 
         * Removes window framing and sets fullscreen mode.
         ******************************************/

        this.setUndecorated(true);
        GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(this);

 /**********************************************
  ******THE ABOVE LINES CAUSE THE ERROR*********
  **********************************************/

        width = this.getWidth();
        height = this.getHeight();

        //Create panel so that I can use key binding which requires JComponent
        mainImagePanel = new PaintPanel();      
        add(mainImagePanel);

        /****************************************** 
         * Key Binding
         ******************************************/

        // Key bound AbstractAction items 
        enterAction = new EnterAction();
        escapeAction = new EscapeAction();

        // Gets the mainImagePanel InputMap and pairs the key to the action
        mainImagePanel.getInputMap().put(KeyStroke.getKeyStroke(enter), "doEnterAction");
        mainImagePanel.getInputMap().put(KeyStroke.getKeyStroke(escape), "doEscapeAction");

        // This line pairs the AbstractAction enterAction to the action "doEnterAction"
        mainImagePanel.getActionMap().put("doEnterAction", enterAction);
        mainImagePanel.getActionMap().put("doEscapeAction", escapeAction);

        /******************************************
         * End Key Binding
         ******************************************/
    }

    //Stretches and displays images in fullscreen window
    private class PaintPanel extends JPanel
    {
        @Override
        public void paintComponent(Graphics g) 
        { 
            if(screenImage != null)
            {
                super.paintComponent(g);
                g.drawImage(screenImage, 0, 0, width, height, this);
            }  
        }
    }

    /******************************************
     * User Input
     ******************************************/

    private class EnterAction extends AbstractAction
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            System.out.println("Enter was pressed.");
        }
    }

    private class EscapeAction extends AbstractAction
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            System.out.println("Program Terminated by ESC Key");
            System.exit(0);
        }
    }

    public static void main(String[] args) 
    {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() 
            {
                FullScreen show = new FullScreen();
                show.setVisible(true);
            }
        });
    }
}

So the below two lines are causing the problem.

this.setUndecorated(true);
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(this);
sage88
  • 4,104
  • 4
  • 31
  • 41
  • Anybody interesting how much code you have? – Roman C Jan 14 '13 at 11:14
  • SSCCE should be **short** man. – Archer Jan 14 '13 at 11:24
  • 1
    Your SSCCE is of no use if it does not reproduce the issue. Moreover, this is definitely not an SSCCE: it is not short (I am sure there are many stuffs in there that can be trimmed because they don't affect your problem directly) and it is not executable (you are reading plenty of stuffs from a file that we don't have). – Guillaume Polet Jan 14 '13 at 11:51
  • Why do you use the default input map `getInputMap()` which as the docs say *Returns the InputMap that is used when the component has focus. This is convenience method for getInputMap(WHEN_FOCUSED).* Or is this the functionality you want? The constructor `getInputMap(int condition)` can accept `WHEN_IN_FOCUSED_WINDOW` and `WHEN_ANCESTOR_OF_FOCUSED_COMPONENT`. See [here](http://docs.oracle.com/javase/7/docs/api/javax/swing/JComponent.html#getInputMap(int)) for more. – David Kroukamp Jan 14 '13 at 13:57
  • It was a shorter SSCCE, but I added back in the buttons exactly as they are and all the variables they require to try to make whatever was causing the problem more apparent. As I said, the minimal version functions. I added a sample text file. I had meant to do so, but forgot when publishing. – sage88 Jan 14 '13 at 16:43
  • @David Kroukamp I did actually already try changing to WHEN_ANCESTOR_OF_FOCUSED_COMPONENT with no change. The actual program is a slideshow of images that get displayed in full screen with setUndecorated(true), so there really isn't a way that the user could unfocus on the JPanel anyway. But you're right it was a good thought, doesn't fix it though. – sage88 Jan 14 '13 at 18:42
  • @Guillaume Polet Hey sorry I labeled it an SSCCE, it was one initially. I added back in the key bindings exactly as they are in my full program in an attempt to reproduce the error and show greater context. Unfortunately that required adding back in a lot of stuff that wasn't central to key binding but rather the action of the bound keys. I added a sample text file above, sorry I had meant to include this. – sage88 Jan 14 '13 at 18:45
  • @archer Aside from adding back in all the button code that is as short as it should be to analyze the problem. It's 432 lines now. The full code is over 2600 lines. However, I will remove the SSCCE since everyone is taking issue with that. – sage88 Jan 14 '13 at 18:50
  • @Guillaume Added an (actual) SSCCE that reproduces the error and I figured out the problematic lines of code. – sage88 Jan 15 '13 at 01:55
  • @David Kroukamp I'm wondering again if your suggestion might be getting at the right idea with fullscreen behaving differently from one system to the next. Modified the code to reproduce the error now and found the problematic lines. – sage88 Jan 15 '13 at 01:57
  • @sage88 Im not sure dont have OS X, but IMO I rarely use the default `InputMap` for `JPanel` Keybindings, normaly, I use `JComponent.WHEN_IN_FOCUSED_WINDOW`, which will detect the key as long as the main container has focus. We would use WHEN_IN_FOCUS perhaps on a JTextArea when key is pressed whilst inside textarea i.e it has focus we would not want it to be catching keys when its not in focus. (not the best example but to illustrate the uses of the different FOCUS variables) – David Kroukamp Jan 15 '13 at 05:18
  • @David Kroukamp Hey I tried changing to all of the different JComponent focus methods with no effect. Your suggestion was a good one, and I had had a similar thought. The code now runs on 2 other macs and my PC, so I think it's just this one machine that has something wrong with it, not the code. Going to throw in the towel on this machine as it was just going to be my test system to make sure the code ran on macs (the 2 macs it does run on are the ones that matter). Thanks for trying! – sage88 Jan 15 '13 at 20:49

3 Answers3

5

http://mail.openjdk.java.net/pipermail/macosx-port-dev/2012-November/005109.html

There is a workaround!

After you make it fullscreen, do frame.setVisible(false); then frame.setVisible(true). Why does it work? Consult the above link.

michaelsnowden
  • 6,031
  • 2
  • 38
  • 83
  • 1
    Awesome, thanks for coming back to this so long after my post. I haven't checked the answer yet as this code has been deployed to a computer that isn't in my control, but I may put together a play example using my SSCCE to test on a mac system I have at home to see if it works. Once I test it, I'll change this to the correct answer if it works. – sage88 Nov 08 '13 at 16:34
  • Yeah, definitely. It does work, but be wary of adding a MouseAdapter: http://stackoverflow.com/questions/19762647/mac-full-screen-jframe-losing-keybindings-from-mouseadapter – michaelsnowden Nov 08 '13 at 22:24
  • I finally got around to testing this bug fix and I can verify that it does work. Thanks @doctordoder! – sage88 Oct 20 '14 at 07:49
3

As noted here, some static final variables may be effectively inlined in a dependent class. Key bindings, which implicitly connect a KeyStroke to a String and that same String to an Action, may exhibit this behavior if the String is defined statically in another class. One simple expedient, suggested here, is to do a full build. If that resolves the problem, you may be able to work backward to mitigate the dependency.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Wouldn't that just cause one of the keybindings to stop working if there happened to be another static string with the same content? All three key bindings don't work. Plus there isn't a single static variable in the whole code, let alone a static String with the same name. – sage88 Jan 14 '13 at 18:59
  • If a full build didn't help, then it's something else. – trashgod Jan 14 '13 at 19:04
  • Additionally, I had been using NetBean's Clean and Build Project feature already just in case of something similar. I believe this accomplishes a full build, but let me know if I need to take it a step further. – sage88 Jan 14 '13 at 19:07
  • No, clean and build is dispositive. The other problem I've seen relates to the two `String` instances not being `equal()`. I usually try to abstract a single `String` constant in the same compilation unit. – trashgod Jan 14 '13 at 22:39
  • So set up something like: private static final String enter = "ENTER"; ? Gave that a try with no effect. I have no idea what's wrong with this computer. The code now works on 3 machines, but had me tearing out my hair on this one. Already tried a fresh install of JDK, may try reinstalling NetBeans, but for now I'm giving up. – sage88 Jan 15 '13 at 00:06
  • I went line by line and pared down to an SSCCE that reproduces the error now. I also found the problematic lines of code. Is there a better method for displaying images in fullscreen since that seems to be causing the problem. – sage88 Jan 15 '13 at 01:58
  • Both your new code and this short [example](http://stackoverflow.com/a/7457102/230513) work for me. You could try `setExtendedState()` on the frame. – trashgod Jan 15 '13 at 09:43
  • Hey I tried setExtendedState(JFrame.MAXIMIZED_BOTH) with no effect. This code is working on 2 other macs and my PC, so I think I'm just going to throw in the towel and say this machine has something wrong with it, and the code is fine. Thanks for trying to help, your suggestions were good ones though apparently not aimed at the problem this computer has. – sage88 Jan 15 '13 at 20:45
  • I managed to put the project into a Jar file for my wife to use on one of the macs that had previously had functional key binding with this code. She couldn't run the Jar file so I downloaded the most recent version of JDK onto that computer. Now the Jar file works, but the key bindings don't. I think that this is a bug with the newest version of JDK for mac OSX. – sage88 Jan 16 '13 at 20:05
2

On a mac system that had functional key binding with this code I installed jdk-7u11-macosx-x64.dmg. The key bindings no longer function after the installation. At this point I'm pretty confident that this is a bug with the new version of JDK for OSX and will be reporting it.

Thanks everyone for trying to help solve this, but it turns out the code is fine.

sage88
  • 4,104
  • 4
  • 31
  • 41
  • 1
    @trashgod I haven't had a chance to test it yet, but looks like doctordoder posted a workaround from people who have had the exact same bug. I still don't think it's been addressed by Oracle though. – sage88 Nov 08 '13 at 16:36