How to create a full screen window on the current monitor with GLFW
Asked Answered
M

3

6

Creating a window with GLFW3 is done using glfwCreateWindow:

GLFWwindow* glfwCreateWindow ( int width,
                               int height,
                               const char *title,
                               GLFWmonitor *monitor,
                               GLFWwindow *share 
                             ) 

If the monitor parameter is not NULL, the window is created in full screen mode on the given monitor. One can receive the primary monitor by calling glfwGetPrimaryMonitor, or chose one of the results of glfwGetMonitors. But how can I create a full screen window on the current monitor, i.e. the monitor the window is currently running in windowed mode? There seems to be no way to receive the currently used monitor. There is glfwGetWindowMonitor, but it only returns the monitor in full screen mode, NULL in windowed mode.

Melo answered 29/1, 2014 at 2:45 Comment(0)
S
17

You can find the current monitor with glfwGetWindowPos/glfwGetWindowSize. This function returns the monitor that contains the greater window area.

static int mini(int x, int y)
{
    return x < y ? x : y;
}

static int maxi(int x, int y)
{
    return x > y ? x : y;
}

GLFWmonitor* get_current_monitor(GLFWwindow *window)
{
    int nmonitors, i;
    int wx, wy, ww, wh;
    int mx, my, mw, mh;
    int overlap, bestoverlap;
    GLFWmonitor *bestmonitor;
    GLFWmonitor **monitors;
    const GLFWvidmode *mode;

    bestoverlap = 0;
    bestmonitor = NULL;

    glfwGetWindowPos(window, &wx, &wy);
    glfwGetWindowSize(window, &ww, &wh);
    monitors = glfwGetMonitors(&nmonitors);

    for (i = 0; i < nmonitors; i++) {
        mode = glfwGetVideoMode(monitors[i]);
        glfwGetMonitorPos(monitors[i], &mx, &my);
        mw = mode->width;
        mh = mode->height;

        overlap =
            maxi(0, mini(wx + ww, mx + mw) - maxi(wx, mx)) *
            maxi(0, mini(wy + wh, my + mh) - maxi(wy, my));

        if (bestoverlap < overlap) {
            bestoverlap = overlap;
            bestmonitor = monitors[i];
        }
    }

    return bestmonitor;
}
Spicy answered 20/7, 2015 at 21:35 Comment(3)
Hey, would you mind clarifying what this code does/how it works?Manteau
GLFWmonitor **monitors; holds a pointer to a pointer of each monitor currently identified by the system. It is populated by glfwGetMonitors(&nmonitors) which also stores the number of monitors identified in the int nmonitors variable. Then it loops through each monitor on the next line and stores the video mode of each one along with the width and height (resolution) of each monitor/ view mode and compares them using the maxi and mini functions. If the monitor tested has a better value (defined by bestoverlap) then it is stored in the bestmonitor object.Schaerbeek
@rbaleksandar the OP knows how to go fullscreen, they just want to know how to get the monitor for fullscreen.Candlestick
M
0

After discussion on IRC it seems that it is not possible to retrieve the currently active monitor (as in the monitor the window is currently drawn on) with GLFW. Therefore it is not possible to create a full screen window on the current monitor.

EDIT: Even though there is no GLFW functionality to directly achieve this, the answer of Shmo provides an elegant solution.

Melo answered 29/1, 2014 at 14:46 Comment(7)
What about using the Windows API to find where your window is located, then querying the resolution of the system and figuring out what monitor you are on that way?Hyo
Yes, but that was not the question. I was looking for a way to do this with GLFW functionality.Melo
Ah, I'm sorry. I was confusing GLFW with WGL which is a Windows way for initializing OpenGL. Since I thought you were using that, I figured a Windows only solution would fit the need. My mistake.Hyo
This means that with GLFW is not possible to go fullscreen? I just have one monitor in my setting.Mote
No, you can go full screen with GLFW (see the original question)! The issue described here affects multi-monitor environments.Melo
See the answer by @Spicy for a solution using GLFW functions.Logjam
Upvoted to counter the -2 downvotes. With glfw, it is trivial to create a full-screen or windowed window. However, identifying the current monitor as opposed to the default monitor (as requested by the initial question) is not. Most 3d games that require full-screen exhibit the same behavior and upon start create a full-screen window on the default monitor, regardless of which monitor currently has "focus".Schaerbeek
C
0

Here is Shmo's answer, ported over to LWJGL:

/** Determines the current monitor that the specified window is being displayed on.
 * If the monitor could not be determined, the primary monitor will be returned.
 * 
 * @param window The window to query
 * @return The current monitor on which the window is being displayed, or the primary monitor if one could not be determined
 * @author <a href="https://mcmap.net/q/1608068/-how-to-create-a-full-screen-window-on-the-current-monitor-with-glfw">Shmo</a><br>
 * Ported to LWJGL by Brian_Entei */
@NativeType("GLFWmonitor *")
public static final long glfwGetCurrentMonitor(long window) {
    int[] wx = {0}, wy = {0}, ww = {0}, wh = {0};
    int[] mx = {0}, my = {0}, mw = {0}, mh = {0};
    int overlap, bestoverlap;
    long bestmonitor;
    PointerBuffer monitors;
    GLFWVidMode mode;

    bestoverlap = 0;
    bestmonitor = glfwGetPrimaryMonitor();// (You could set this back to NULL, but I'd rather be guaranteed to get a valid monitor);

    glfwGetWindowPos(window, wx, wy);
    glfwGetWindowSize(window, ww, wh);
    monitors = glfwGetMonitors();

    while(monitors.hasRemaining()) {
        long monitor = monitors.get();
        mode = glfwGetVideoMode(monitor);
        glfwGetMonitorPos(monitor, mx, my);
        mw[0] = mode.width();
        mh[0] = mode.height();

        overlap =
                Math.max(0, Math.min(wx[0] + ww[0], mx[0] + mw[0]) - Math.max(wx[0], mx[0])) *
                Math.max(0, Math.min(wy[0] + wh[0], my[0] + mh[0]) - Math.max(wy[0], my[0]));

        if (bestoverlap < overlap) {
            bestoverlap = overlap;
            bestmonitor = monitor;
        }
    }

    return bestmonitor;
}
Cessionary answered 1/1, 2020 at 19:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.