Search code examples
c#windowopentk

What is the proper way to change starting monitors with OpenTK?


I am trying to get the CurrentMonitor property of NativeWindowSettings to change which monitor it creates the window on. I'm trying to display on my secondary monitor, here is what I have:

        var nativeWindowSettings = new NativeWindowSettings()
        {
            Size = new OpenTK.Mathematics.Vector2i(800, 600),
            Title = "My Window",
            Flags = OpenTK.Windowing.Common.ContextFlags.ForwardCompatible,
            CurrentMonitor = new Monitors.GetMonitors()[1].Handle, //problem
            
        };

        using (var window = new Game(GameWindowSettings.Default, nativeWindowSettings))
        {
            window.Run();
        }

I've tried creating a new Monitor Handle and assigning it to that, and I've tried creating a new MonitorHandle using the pointer from the second monitor in the array of monitors.

CurrentMonitor = new MonitorHandle(Monitors.GetMonitors()[1].Handle.Pointer),

Solution

  • It depends on your OS. Not all window systems give you the ability to specify which screen a newly-created window will appear on, and not all of them are going to pay attention to that parameter either. Your mileage may vary, as they say. You didn’t specify which OS you’re on, so I’m going to assume for the rest of this that it’s some flavor of Microsoft Windows.

    On MS Windows, you don’t get to specify which screen your new window appears on without also specifying exactly where on that screen the window should appear: If you let Windows pick the coordinates, it’s going to put the window on the primary screen every time, exactly as you’ve seen it doing.

    So the right way to go about it, at least on MS Windows, is to first find out the virtual coordinates of the screen (the MonitorInfo) that you want to create the window on. You can choose from its ClientArea (the virtual coordinates of the entire screen) or its WorkArea (the virtual coordinates of the usable part of that screen, minus things like the taskbar). In either case, each MonitorInfo’s rectangle will be a unique chunk of virtual screen space that doesn’t overlap that of any of the others.

    Once you’ve found the rectangle of the screen you want to create the window on, you just specify a Location in the NativeWindowSettings that’s on that screen, inside the coordinates of its ClientArea or WorkArea: Possibly in the top corner, or, if you want to be a bit more clever, you can do some math and center the window in that virtual rectangle. The only thing you can’t easily do is the OS’s “cascading” behavior, where your window will be given a new position that’s sort-of distinct from the others on the screen but not really centered and not really in the top corner either; that behavior is built-in inside the window system, and there’s no way to directly access it or influence it.

    But that’s otherwise it: You don’t specify the monitor: You specify a Location that’s on the monitor, and then the window will appear there. That’s not really an OpenTK thing, either: That’s just how Microsoft Windows does a multi-monitor setup.