Positioning an initially fullscreen window

Hi all,

I’ve started using glfwSetWindowMonitor to switch back and forth between windowed and fullscreen, and I realised I don’t actually know how to implement this properly.

Switching from windowed to fullscreen and back again in that order is easy: I just cache the position and size of the window, then restore those values later. If the window is created fullscreen, however, to turn it into a window I need to specify a position, and I don’t know the best way to do that!

I thought 0,0 would be a sensible guess, but since it sets the position of the client area, that guarantees any title bar and frame will be offscreen. Less than ideal. I tried using glfwGetWindowFrameSize to figure out an offset, but predictably that returns 0 for a fullscreen window.

How do others manage this? I’d love to know!

-tombsar

I use the following:

  1. Default to 50,50 position for windows.
  2. Save the position on exit to a config file, restore that when user re-opens app.

An alternative to 1 is to choose a random position which is permits the window size to be fully contained by the screen, allowing for a large border for the frame and since TVs don’t display the outer edge of the screen.

Optionally you could check glfwGetWindowFrameSize after positioning the window and move it if needed. However so long as a decent amount of the frame is showing the user should be able to drag it onto the screen if needed - saving the position to a config is the optimal solution in my view as this should result in what the user wants.

Thanks @dougbinks. Glad to know I’m not missing something obvious.

I did try that, but unfortunately on X11 there’s a long delay between requesting the window leave fullscreen and it actually taking effect, so I can’t check the frame size immediately. I could probably use the window size callback to get at the information as soon as possible, but I didn’t try because I don’t like the idea of moving the window if I can avoid it.

Another idea that’s just occurred is to centre the client area in the monitor. I feel that’s reasonable, and fairly safe.

This is what I’ve settled on for now:

static void toggleFullscreen (GLFWwindow * window) {
	static _Bool position_saved;
	static int saved_x;
	static int saved_y;
	static int saved_w;
	static int saved_h;
	
	GLFWmonitor * monitor = glfwGetWindowMonitor(window);
	
	if (monitor) {
		int x, y, w, h;
		if (position_saved) {
			x = saved_x;
			y = saved_y;
			w = saved_w;
			h = saved_h;
		} else {
			int wa_x, wa_y, wa_w, wa_h;
			glfwGetMonitorWorkarea(monitor, &wa_x, &wa_y, &wa_w, &wa_h);
			
			x = wa_x + wa_w/2 - DEFAULT_WINDOW_WIDTH/2;
			y = wa_y + wa_h/2 - DEFAULT_WINDOW_HEIGHT/2;
			w = DEFAULT_WINDOW_WIDTH;
			h = DEFAULT_WINDOW_HEIGHT;
		}
		glfwSetWindowMonitor(window, NULL, x, y, w, h, GLFW_DONT_CARE);
	} else {
		glfwGetWindowPos(window, &saved_x, &saved_y);
		glfwGetWindowSize(window, &saved_w, &saved_h);
		position_saved = 1;
		
		monitor = glfwGetPrimaryMonitor();
		GLFWvidmode const * mode = glfwGetVideoMode(monitor);
		
		glfwSetWindowMonitor(
		    window,
		    monitor,
		    0,
		    0,
		    mode->width,
		    mode->height,
		    mode->refreshRate
		);
	}
}