Search code examples
javalibgdxawtlwjgldesktop

How to toggle fullscreen borderless on multiple monitors properly


I was looking for a way to properly choose the monitor I want to fullscreen on based on the position of the window prior to fullscreening.

I looked online for ages but couldn't find anything so I ended up trying a bunch of things until I got something working.

I figured someone eventually will try to look this problem up and I might as well share my solution.


Solution

  • What I ended up doing is get the virtual screen coordinates of the center of the window using LWJGL2's Display class like so:

    int x = Display.getX() + Display.getWidth()/2, 
        y = Display.getY() + Display.getHeight()/2;
    

    I then used AWT to get all available monitors:

    GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()
    

    I iterated through them and got their virtual bounds(and applied any DPI scaling they might have):

    Rectangle bounds = screenDevice.getDefaultConfiguration().getDefaultTransform().createTransformedShape(screenDevice.getDefaultConfiguration().getBounds()).getBounds();
    

    EDIT: Slightly altered line so it can support Windows' DPI scaling properly.

    If the bounds contained the center of the window, it means that most of the window is probably within that monitor:

    if(bounds.contains(x,y))
        return bounds; //getMonitorFromWindow()
    

    Then to toggle between windowed borderless fullscreen and normal windowed in LibGDX I did the following:

    // config is the LwjglApplicationConfiguration of the application
    
    // upon changing using alt+enter
    if(fullscreen) {
        config.resizable = false;
        Gdx.graphics.setUndecorated(true);
        Rectangle monitor = getMonitorFromWindow();
        // set to full screen in current monitor
        Gdx.graphics.setWindowedMode(monitor.width, monitor.height);
        Display.setLocation(monitor.x, monitor.y);
    } else {
        config.resizable = true;
        Gdx.graphics.setUndecorated(false);
        Rectangle monitor = getMonitorFromWindow();
        // set to windowed centered in current monitor
        Gdx.graphics.setWindowedMode((int) (monitor.width * 0.8f), (int) (monitor.height * 0.8f));
        Display.setLocation(monitor.x + (int) (monitor.width * 0.1f), monitor.y + (int) (monitor.height * 0.1f));
    }
    

    I hope someone would find this useful.