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

Improper canvas size when using scaled resolutions on macOS #26

Open
nathan-fiscaletti opened this issue Jul 5, 2020 · 1 comment
Open

Comments

@nathan-fiscaletti
Copy link

For some reason, my canvas is not the same size as the initial values i had originally passed to sdlcanvas.CreateWindow().

Here is some sample code.

package main

import(
    "fmt"
    "github.com/tfriedel6/canvas"
    "github.com/tfriedel6/canvas/sdlcanvas"
    "github.com/tfriedel6/canvas/backend/softwarebackend"
)

func main() {
    // The size i would like my window to be
    screenW := 1600
    screenH := 900

    // The size i would like the draggable square in the center to be.
    squareSize := 128

    wnd, cv, err := sdlcanvas.CreateWindow(screenW, screenH, "Example")
    if err != nil {
        panic(err)
    }

    fmt.Printf("Desired: %v w x %v h\n", screenW, screenH)
    fmt.Printf("Actual: %v w x %v h\n", cv.Width(), cv.Height())

    // Create a square. This square will be displayed in the center
    // of the window and should be draggable.
    backend := softwarebackend.New(squareSize, squareSize)
    cvImg := canvas.New(backend)
    cvImg.SetFillStyle("#FFF")
    cvImg.Rect(0, 0, 64, 64)
    cvImg.Fill()
    img := cvImg.GetImageData(0, 0, squareSize, squareSize)

    // Load the square into the main canvas as an image.
    imgFinal, err := cv.LoadImage(img)
    if err != nil {
        panic(err)
    }

    // Starting position for the square
    xStartPos := (screenW / 2) - (squareSize / 2)
    yStartPos := (screenH / 2) - (squareSize / 2)

    // Active position for the square
    xPos := xStartPos
    yPos := yStartPos

    // Basic properties for tracking the cursor
    followMouse := false

    // When the mouse is released, stop following it and 
    // snap the square back to it's original pos.
    wnd.MouseUp = func(b, x, y int) {
        followMouse = false
        xPos = xStartPos
        yPos = yStartPos
    }

    // Only begin following the cursor if the square is clicked.
    wnd.MouseDown = func(b, x, y int) {
        if x > xStartPos && x < xStartPos + squareSize {
            if y > yStartPos && y < yStartPos + squareSize {
                followMouse = true
            }
        }
    }

    // When the mouse is moved, if we should be following the cursor
    // update the location of the square to match that of the cursor.
    wnd.MouseMove = func(x, y int) {
        if followMouse {
            xPos = x - (squareSize / 2)
            yPos = y - (squareSize / 2)
        }
    }

    defer wnd.Destroy()

    // Start the main loop for rendering.
    wnd.MainLoop(func() {
        // I've been able to determine that for some reason, my canvas
        // is not the same size as the initial values i had originally
        // passed to sdlcanvas.CreateWindow().

        // This seems to properly fill the entire canvas
        w, h := float64(cv.Width()), float64(cv.Height())
        cv.SetFillStyle("#fff")
        cv.FillRect(0, 0, w, h)

        // This does not fill the entire canvas.
        w2, h2 := float64(screenW), float64(screenH)
        cv.SetFillStyle("#000")
        cv.FillRect(0, 0, w2, h2)

        // This should be in the center of the window when it is first
        // spawned but instead is is in the center of the top left
        // quadrant of the window, which happens to be the center of
        // the true canvas.
        cv.DrawImage(imgFinal, float64(xPos), 
                               float64(yPos), 
                               float64(squareSize), 
                               float64(squareSize))
    })
}

When I run it, I get this output:

Output display

$ go run main.go
Desired: 1600 w x 900 h
Actual: 3200 w x 1800 h

I'm wondering if this has something to do with macOS' scaling features?

--

After doing some more testing, I've found that if I change my display to "default for display", I get a different "actual" value.

Desired: 1600 w x 900 h
Actual: 2048 w x 1090 h

I'm confident now that this has at least something to do with macOS' scaling features.

image

This testing was all done on a Late 2015 Mac Book Pro.

@tfriedel6
Copy link
Owner

Hi,

sorry for the really late response. I couldn't test it right away, and then lost track of it...

Anyway, in case it is still relevant, yes it is due to the display scaling. When you create a window with some size, macOS just automatically scales it up if you have set the display to scale. Since that means you have a higher physical resolution in the window, you need to then query the actual size by using the cv.Width() and cv.Height() functions.

If you want to create a window with a certain physical resolution, regardless of the scale factor, then you will have to find out the scale factor somehow. I know on iOS you can query it (on UIScreen there is a scale property), but I don't know if there is an equivalent for macOS.

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

2 participants