Skip to content

getDisplayBounds() for nimx #516

@MCRusher

Description

@MCRusher

I like to scale my windows based on the monitor resolution, which most gui libraries have a mechanism to allow.

But I haven't been able to find a way to get this info in nimx without manually stepping into SDL2 or winapi

I have both an SDL2 implementation as well as a winapi implementation I've written for nimx for my application to allow this, I haven't written a linux or macos version since I can't test them currently (and I'd never be able to test a mac version, I don't own a mac)

It'd be nice to have this functionality in nimx itself, and if you find my code useful and not broken code that just happens to work, feel free to use it.

If it's acceptable (which I doubt since you might not want it calling quit), I'd be willing to make a PR myself if you'd like, though I'm not sure where best to put it, maybe in the nimx/private/windows/XX_window.nim files?

from nimx/types import Rect, newRect

proc getDisplayBounds*(): Rect

when defined(nimxAvoidSDL):
    when defined(windows):
        import winim/lean except RECT
        proc WinQuit() {.noreturn.} =
            var msg = newWString(4096)
            FormatMessage(
                dwFlags=FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_IGNORE_INSERTS,
                lpSource=nil,
                dwMessageId=GetLastError(),
                dwLanguageId=DWORD MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                lpBuffer=msg,
                nSize=4096,
                Arguments=nil
            )
            quit($msg)
        proc getDisplayBounds(): Rect =
            let monitor = MonitorFromPoint(POINT(x: 0, y: 0), MONITOR_DEFAULTTOPRIMARY)
            var mInfo = MONITORINFO(cbSize: cast[DWORD](sizeof MONITORINFO))
            if GetMonitorInfo(monitor, mInfo.addr) == 0:
                WinQuit()
            let mb = mInfo.rcMonitor
            return newRect(mb.left.float32, mb.top.float32, (mb.right - mb.left).float32, (mb.bottom - mb.top).float32)
    elif defined(linux):
        import x11/xlib
        proc getDisplayBounds(): Rect =
            let display = XOpenDisplay(nil)
            if display == nil:
                quit("Could not open display")
            let screen = DefaultScreenOfDisplay(display)
            if screen == nil:
                quit("Could not get screen from display")
            
            let width = WidthOfScreen(screen)
            let height = HeightOfScreen(screen)

            return newRect(0, 0, width.float32, height.float32)
    else:
        {.fatal: "Not implemented".}
else:
    from sdl2 import nil
    proc getDisplayBounds(): Rect =
        if sdl2.wasInit(sdl2.InitVideo) == 0: # video subsystem has not been initialized
            if sdl2.initSubsystem(sdl2.InitVideo) != 0: # allows this function to be called before newWindow
                quit($sdl2.getError())
        var r: sdl2.Rect
        if sdl2.getDisplayBounds(0, r) != sdl2.SdlSuccess:
            quit($sdl2.getError())
        return newRect(r.x.float32, r.y.float32, r.w.float32, r.h.float32)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions