glfwGetVideoMode retrieving incorrect size on second monitor

Started by Eli Jergensen, December 26, 2016, 22:52:55

Previous topic - Next topic

Eli Jergensen

Hello All!

I am currently fighting through all of the work to spawn a fullscreen window on the second monitor of a two-monitor setup. However, I am running into problems with the size of the window while on the second monitor.

For the example below, both monitors are at a resolution of 1920 x 1080. The second monitor is configured to sit directly above the first, so the secondary monitor position is (0, -1080) in screen coordinates. This example is running in LWJGL 3.1 on Windows 10.

import org.lwjgl.PointerBuffer;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;

import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent;
import static org.lwjgl.glfw.GLFW.glfwShowWindow;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glClearColor;
import static org.lwjgl.system.MemoryUtil.NULL;

public class Main{

    public static void main (String[] args) {


        if(!glfwInit()){
            System.out.println("ERROR: could not instantiate glfw");
            System.exit(401);
        }

        int monitorIndex = 1; // use the 2nd monitor

        PointerBuffer monitorsBuffer = glfwGetMonitors();
        monitorsBuffer.position(0); // ensure that we are at the 0th position

        if (!(monitorIndex < monitorsBuffer.remaining() && monitorIndex >= 0)) {
            // if the monitorIndex is not a valid index, revert to 0 (the primary monitor)
            monitorIndex = 0;
        }

        long monitor = monitorsBuffer.get(monitorIndex); // grab the monitor from the buffer
        GLFWVidMode videoMode = glfwGetVideoMode(monitor); // grab the video mode from the buffer

        /////////////////////////////////////////////////////////////////////
        System.out.println("Video Modes of Monitor number " + monitorIndex);
        System.out.println("Actual video mode: " + videoMode.width() + " x " + videoMode.height());
        for(int i = 0; i < glfwGetVideoModes(monitor).limit(); i++) {
            System.out.println(glfwGetVideoModes(monitor).get(i).width() + " x " + glfwGetVideoModes(monitor).get(i).height());
        }
        /////////////////////////////////////////////////////////////////////

        boolean fullscreen = true; // set the window to fullscreen
        int w, h;
        if (fullscreen) {
            w = videoMode.width(); // if fullscreen, grab the entire width and height of the screen
            h = videoMode.height();
        } else {
            w = 960;
            h = 520;
        }
        long displayMonitor = NULL;

        // apply versioning and window hints
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, 1);
        glfwWindowHint(GLFW_STENCIL_BITS, 4);
        glfwWindowHint(GLFW_SAMPLES, 4);
//        glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);

        glfwWindowHint(GLFW_RED_BITS, videoMode.redBits()); // ensure that the current video mode sticks around
        glfwWindowHint(GLFW_GREEN_BITS, videoMode.greenBits());
        glfwWindowHint(GLFW_BLUE_BITS, videoMode.blueBits());
        glfwWindowHint(GLFW_REFRESH_RATE, videoMode.refreshRate());
        glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);

        // create the actual window (w, h, name, pass long for fullscreen, window to inherit properties from!!!!)
        long windowHandle = glfwCreateWindow(w, h, "TEMP NAME", displayMonitor, NULL);

        videoMode = glfwGetVideoMode(monitor); // grab the video mode again, in case it changed when we made the window
        if (fullscreen) {
            w = videoMode.width(); // if fullscreen, grab the entire width and height of the screen
            h = videoMode.height();
        } else {
            w = 960/4;
            h = 520/4;
        }

        // Center the window on the monitor desired
        int[] monitorLeft = new int[1]; // x - coord of left side of monitor where window is on
        int[] monitorBottom = new int[1]; // y - coord of bottom of monitor where window is on
        glfwGetMonitorPos(monitor, monitorLeft, monitorBottom); // can't use monitor, cause monitor is NULL

        // Bottom-Left corner of screen plus half the width/height of the screen gives center of screen
        // Subtracting half of the size of the window itself gives the bottom-left corner of the window
        int windowXPos = monitorLeft[0] + videoMode.width()/2 - w/2;
        int windowYPos = monitorBottom[0] + videoMode.height()/2 - h/2;
        System.out.println("MonitorX: " + monitorLeft[0]);
        System.out.println("MonitorY: " + monitorBottom[0]);
        System.out.println("WindowX: " + windowXPos);
        System.out.println("WindowY: " + windowYPos);
        System.out.println("MonitorWidth: " + videoMode.width());
        System.out.println("MonitorHeight: " + videoMode.height());
        System.out.println("WindowWidth: " + w);
        System.out.println("WindowHeight: " + h);
        glfwSetWindowMonitor(windowHandle, displayMonitor, windowXPos, windowYPos, w, h, GLFW_DONT_CARE);
//        glfwSetWindowPos(windowHandle, windowXPos, windowYPos); // actually set the position of the window
//        glfwSetWindowSize(windowHandle, w, h); // actually set the size of the window

        videoMode = glfwGetVideoMode(monitor);
        System.out.println("Actual VideoMode: " + videoMode.width() + " x " + videoMode.height());


        ///////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////

        // Make the window focused and visible
        glfwMakeContextCurrent(windowHandle);
        glfwShowWindow(windowHandle);
        // sets up OpenGL context in THIS THREAD
        GL.createCapabilities();



        int i = 5;
        while(i >= 0) {

            glClearColor(1.0f, 0.0f, 0.0f, 0.0f); // fill the window with red
            glClear(GL_COLOR_BUFFER_BIT);

            glfwSwapBuffers(windowHandle);

            // just spin idly for 5 seconds to prove that the window exists
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(-500);
            }

            i--; // next second
        }
    }
}


Under the conditions as specified above, the window is aligned with the upper left corner of the monitor (as it should be), but it extends too far below and to the right, drawing a few hundred lines of pixels on the monitor below it. This happens both when I try to make an actual fullscreen window and when I make a "windowed fullscreen" window.

Does anyone know why this is happening and what I can do to fix it?

Other information: if I change the resolution on the first monitor, it seems to have no effect on the window. If I change the resolution on the second monitor to 1600 x 900, the window looks correct. If I change the resolution on the second monitor to 1360 x 768, the window is too small and it's bottom left corner is aligned to the bottom left corner of the second monitor.

spasi

I cannot reproduce what you describe. Either using fullscreen (monitor != NULL) or windowed fullscreen (undecorated and monitor == NULL) results in the second monitor being completely covered without spilling to the primary monitor.

The code above is a bit confusing and it's not clear what you're trying to do. Could you provide a screenshot of what you're seeing and some more details about your system?