001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.actions;
003
004import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
005import static org.openstreetmap.josm.tools.I18n.tr;
006
007import java.awt.Frame;
008import java.awt.GraphicsDevice;
009import java.awt.GraphicsEnvironment;
010import java.awt.Rectangle;
011import java.awt.Window;
012import java.awt.event.ActionEvent;
013import java.awt.event.KeyEvent;
014import java.util.ArrayList;
015import java.util.List;
016
017import javax.swing.JComponent;
018import javax.swing.JFrame;
019import javax.swing.KeyStroke;
020
021import org.openstreetmap.josm.Main;
022import org.openstreetmap.josm.gui.util.GuiHelper;
023import org.openstreetmap.josm.tools.Shortcut;
024
025/**
026 * This class toggles the full-screen mode.
027 * @since 2533
028 */
029public class FullscreenToggleAction extends ToggleAction {
030    private final transient GraphicsDevice gd;
031    private Rectangle prevBounds;
032
033    /**
034     * Constructs a new {@code FullscreenToggleAction}.
035     */
036    public FullscreenToggleAction() {
037        super(tr("Fullscreen view"),
038              null, /* no icon */
039              tr("Toggle fullscreen view"),
040              Shortcut.registerShortcut("menu:view:fullscreen", tr("Toggle fullscreen view"), KeyEvent.VK_F11, Shortcut.DIRECT),
041              false /* register */
042        );
043        putValue("help", ht("/Action/FullscreenView"));
044        putValue("toolbar", "fullscreen");
045        Main.toolbar.register(this);
046        gd = GraphicsEnvironment.isHeadless() ? null : GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
047        setSelected(Main.pref.getBoolean("draw.fullscreen", false));
048        notifySelectedState();
049    }
050
051    @Override
052    public void actionPerformed(ActionEvent e) {
053        toggleSelectedState(e);
054        Main.pref.put("draw.fullscreen", isSelected());
055        notifySelectedState();
056        setMode();
057    }
058
059    /**
060     * To call if this action must be initially run at JOSM startup.
061     */
062    public void initial() {
063        if (isSelected()) {
064            setMode();
065        }
066    }
067
068    protected void setMode() {
069        JFrame frame = (JFrame) Main.parent;
070
071        List<Window> visibleWindows = new ArrayList<>();
072        visibleWindows.add(frame);
073        for (Window w : Frame.getWindows()) {
074            if (w.isVisible() && w != frame) {
075                visibleWindows.add(w);
076            }
077        }
078
079        boolean selected = isSelected();
080
081        if (frame != null) {
082            frame.dispose();
083            frame.setUndecorated(selected);
084
085            if (selected) {
086                prevBounds = frame.getBounds();
087                frame.setBounds(new Rectangle(GuiHelper.getScreenSize()));
088            }
089        }
090
091        // we cannot use hw-exclusive fullscreen mode in MS-Win, as long
092        // as josm throws out modal dialogs.
093        //
094        // the good thing is: fullscreen works without exclusive mode,
095        // since windows (or java?) draws the undecorated window full-
096        // screen by default (it's a simulated mode, but should be ok)
097        String exclusive = Main.pref.get("draw.fullscreen.exclusive-mode", "auto");
098        if (("true".equals(exclusive) || ("auto".equals(exclusive) && !Main.isPlatformWindows())) && gd != null) {
099            gd.setFullScreenWindow(selected ? frame : null);
100        }
101
102        if (!selected && prevBounds != null && frame != null) {
103            frame.setBounds(prevBounds);
104        }
105
106        for (Window wind : visibleWindows) {
107            if (wind != null) {
108                wind.setVisible(true);
109            }
110        }
111
112        // Free F10 key to allow it to be used by plugins, even after full screen (see #7502)
113        if (frame != null) {
114            frame.getJMenuBar().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_F10, 0), "none");
115        }
116    }
117}