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

There doesn't seem to be a way to make a Window fullscreen after creating it if you don't happen to have a spare &Glfw outside of your Window #490

Open
PatchMixolydic opened this issue Dec 22, 2021 · 2 comments

Comments

@PatchMixolydic
Copy link

PatchMixolydic commented Dec 22, 2021

The recommended way to set a window to fullscreen after creating it seems to be glfwSetWindowMonitor. The wrapper for this, Glfw::set_monitor, takes a WindowMode<'_>. In order to use WindowMode::Fullscreen, you need a reference to a Monitor. The only ways to get such a reference seem to be Glfw::with_primary_monitor or Glfw::with_connected_monitors, both of which require a closure so that the &Monitor they yield can only live within that closure.

I'm designing a backend-agnostic graphics framework for a game engine. To that end, I have a trait like this:

// need to be able to use this as a trait object with no generics necessary
// (ie. no associated types allowed, otherwise you'd have to specify them)
trait Window {
    // various functions
    fn set_fullscreen(&mut self, fullscreen: bool);
}

When trying to implement this for GLFW, however, it quickly becomes apparent that the borrow checker isn't pleased with my harebrained scheme:

struct GlfwWindow {
    window: glfw::Window,
    // ...
}

impl Window for GlfwWindow {
    fn set_fullscreen(&mut self, fullscreen: bool) {
        if self.fullscreen == fullscreen {
            return;
        }

        self.fullscreen = fullscreen;

        if !fullscreen {
            self.window.set_monitor(WindowMode::Windowed, ...);
            return;
        }

        // Can't have a `glfw` parameter (there's no way to specify its type),
        // have to use the field on `self.window`
        self.window.glfw.with_primary_monitor(|glfw, maybe_monitor| {
            let monitor = maybe_monitor.unwrap();
            let video_mode = monitor.get_video_mode().unwrap();

            // ERROR self.window is borrowed as mutable for
            // the duration of the call to `with_primary_monitor`
            self.window.set_monitor(
                WindowMode::Fullscreen(monitor),
                0,
                0,
                video_mode.width,
                video_mode.height,
                None
            );
        });
    }
}

Due to this, I seem to be at an impasse. I can't recreate the window on the fly since my trait for glfw::Glfw and similar (Backend) requires associated types and therefore would require generics to use it in a trait object.

If the real issue is a severe design flaw on my end or if providing an API for this is intractable/impossible, please feel free to close this issue.

@PatchMixolydic
Copy link
Author

For the sake of posterity, one can use Window::set_decorated and Window::set_size to attain borderless fullscreen, but this might not be usable for games that need more resources or low input latency.

@PatchMixolydic
Copy link
Author

PatchMixolydic commented Jan 1, 2022

I seem to be terrible at remembering and worse at reading. There is, in fact, a way to use ffi::glfwSetWindowMonitor (the original issue used to claim that there wasn't) thanks to <Window as Context>::window_ptr. However, doing so seems to give me an error from Xorg (which may be because the code I threw together to test this is unsound):

X Error of failed request:  BadRRCrtc (invalid Crtc parameter)
  Major opcode of failed request:  140 (RANDR)
  Minor opcode of failed request:  20 (RRGetCrtcInfo)
  Crtc id in failed request: 0xef600101
  Serial number of failed request:  990
  Current serial number in output stream:  990

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

No branches or pull requests

1 participant