Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot toggle fullscreen from key callback function #903

Open
Wqer555 opened this issue Nov 22, 2016 · 7 comments
Open

Cannot toggle fullscreen from key callback function #903

Wqer555 opened this issue Nov 22, 2016 · 7 comments
Labels

Comments

@Wqer555
Copy link

Wqer555 commented Nov 22, 2016

The intended result of calling glfwSetWindowMonitor() is correct outside of the callback function, but not inside of it. It can switch fullscreen to windowed, but not the other way around.

#include <iostream>
#include <GLFW/glfw3.h>

int main() {
  if(!glfwInit()) exit(1);
  glfwSetErrorCallback([](const int error, const char *desc) {
    std::cerr << error << ": " << desc << '\n';
  });
  glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
  //GLFWwindow *window = glfwCreateWindow(640, 480, "Hello World", nullptr, nullptr);
  GLFWwindow *window = glfwCreateWindow(640, 480, "Hello World", glfwGetPrimaryMonitor(), nullptr);
  glfwMakeContextCurrent(window);
  glfwSetKeyCallback(window, [](GLFWwindow *window, int key, int, int action, int) {
      if(key == GLFW_KEY_F12 && action == GLFW_PRESS)
        glfwSetWindowMonitor(window, glfwGetWindowMonitor(window), 0, 0, 640, 480, 60);
    });
  //glfwSetWindowMonitor(window, glfwGetPrimaryMonitor(), 0, 0, 640, 480, 60);
  glfwSetWindowMonitor(window, nullptr, 0, 0, 640, 480, 60);
  while(!glfwWindowShouldClose(window)) {
    glfwPollEvents();
    glClear(GL_COLOR_BUFFER_BIT);
    glfwSwapBuffers(window);
  }
  glfwDestroyWindow(window);
  glfwTerminate();
}
@elmindreda
Copy link
Member

elmindreda commented Nov 27, 2016

Your key callback sets the monitor (if any) that the window already has, so it shouldn't ever switch between windowed and full screen. Here is an example of a key callback toggling between windowed and full screen modes.

@elmindreda elmindreda self-assigned this Nov 27, 2016
@elmindreda elmindreda added the question Please use the support label instead label Nov 27, 2016
@Wqer555
Copy link
Author

Wqer555 commented Nov 28, 2016

I still don't understand how the call to glfwSetWindowMonitor does exactly what I want in main but not in the key callback.

From the documentation of glfwSetWindowMonitor:

This function sets the monitor that the window uses for full screen mode or, if the monitor is NULL, makes it windowed mode.

If I understand this correctly, the function changes the window to full screen when given a monitor, otherwise it changes to windowed mode. This is the behavior that the function exhibits when being called from main, but not from the key callback.

Using the code you linked, the window moves to the 0, 0 position of the monitor that it is currently in, but is windowed, even when given a monitor. This is regardless of whether the window was created full screen or windowed. Creating the window full screen works perfectly, however I still haven't been able to switch to full screen after the window has been created.

I also noticed this error, although I'm not sure what caused it and I don't know how to reproduce it:

65544: X11: Iconification of full screen windows requires a WM that supports EWMH full screen

@Wqer555
Copy link
Author

Wqer555 commented Nov 28, 2016

I tested to see if it was my desktop environment causing the problem. I noticed that I can get toggling to work in Unity by using glfwGetPrimaryMonitor, but it doesn't work in DWM. This is odd because creating the window as full screen and changing it to fullscreen in main both work in DWM.

@elmindreda elmindreda added the X11 label Nov 29, 2016
@elmindreda
Copy link
Member

elmindreda commented Nov 29, 2016

If I understand this correctly, the function changes the window to full screen when given a monitor, otherwise it changes to windowed mode. This is the behavior that the function exhibits when being called from main, but not from the key callback.

Because in the key callback you set the monitor to the current monitor (if any) of the window as returned by glfwGetWindowMonitor, so if it's in windowed mode then you set it to windowed mode and if it's full screen on a monitor you make it full screen on that monitor.

noticed that I can get toggling to work in Unity by using glfwGetPrimaryMonitor, but it doesn't work in DWM. This is odd because creating the window as full screen and changing it to fullscreen in main both work in DWM.

As a tiled window manager, DWM has some unusual ideas about window placement. What version of DWM are you using?

I also noticed this error, although I'm not sure what caused it and I don't know how to reproduce it:
65544: X11: Iconification of full screen windows requires a WM that supports EWMH full screen

What is the output of xprop -root on the DWM machine?

@Wqer555
Copy link
Author

Wqer555 commented Nov 29, 2016

I decided to remove glfwSetKeyCallback and use glfwGetKey instead to see if it would work.

In the main loop:
glfwSetWindowMonitor(window, glfwGetPrimaryMonitor(), 0, 0, 640, 480, 60); // Works

Alternatively:

if(glfwGetKey(window, GLFW_KEY_F12) == GLFW_PRESS)
  glfwSetWindowMonitor(window, glfwGetPrimaryMonitor(), 0, 0, 640, 480, 60); // Fails

The first example works every time. The second fails. I'm positive that the code is executed since debug statements work in the conditional.

I think the same problem as with the callback function is happening here.

I did some more testing:

if(true)
  glfwSetWindowMonitor(window, glfwGetPrimaryMonitor(), 0, 0, 640, 480, 60); // Works
if(time == 50) // Number of iterations of main loop
  glfwSetWindowMonitor(window, glfwGetPrimaryMonitor(), 0, 0, 640, 480, 60); // Fails

It seems that glfwSetWindowMonitor only sometimes works if it is in an if conditional. I am sure the expression is true in these examples.

@Wqer555
Copy link
Author

Wqer555 commented Feb 5, 2017

I decided to get back to this. It still confuses me how glfwSetWindowMonitor works alone, but when in an if statement, even if the condition is true, it doesn't.

If the window is started windowed and glfwSetWindowMonitor(glfwGetPrimaryMonitor(), 0, 0, 640, 480, 60) is called, the window is set to fullscreen, but only after the second time. The first time the key is pressed, it changes the resolution, but parts of the desktop are still visible. If the window moves away from the top left of the monitor, it may not be visible. After the second time, it becomes fullscreen with nothing but the window visible.

If the window is started fullscreen, a similar behavior occurs. It takes a call to glfwSetWindowMonitor to make it really fullscreen. Otherwise the desktop is still visible.

I decided to look at the source code of GLFW to see if I could find anything. In x11_window.c, in _glfwPlatformSetWindowMonitor, there is a bit of code:

if (waitForVisibilityNotify(window))
  acquireMonitor(window);

If
if (waitForVisibilityNotify(window))
is commended out, the behavior changes.

Now toggling to fullscreen works from a key but it still takes 2 calls to do it. In other words, it takes either switching to it twice or creating the window fullscreen and switching to it again. Switching to windowed takes only one call.

@elmindreda elmindreda removed their assignment Apr 27, 2017
@elmindreda elmindreda removed question Please use the support label instead waiting labels Apr 30, 2017
@ghost
Copy link

ghost commented Feb 8, 2018

Fullscreen switching/toggling during runtime won't work on dwm v6.1 without any patches. It simply forces it back into windowed mode. Also, if you toggle the bar of dwm and the window has been started in fullscreen mode, dwm forces it into windowed mode also. So glfwSetWindowMonitor simply won't work on dwm.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants