Home > Back-end >  account for mac display scaling (any language)
account for mac display scaling (any language)

Time:10-01

I have been a windows user almost all my life, and whenever I would define a window size on any graphical application (pygame, jframes, glfw etc...) the window would appear exactly that size in pixels.

However, since moving to macOS I have noticed that thats not the case, and there is some kind of scaling happening in the background, and I want to know how I can reverse this so that I can get the intended screen sizes. Here are some examples.

This is a pygame window that is defined to be 1920x1080 in size. My laptop display has a resolution of 2560 x 1600 so a 1080p window should be able to fit easily but it doesnt pygame 1080p window

of course, I could just decrease the window size which is what I tend to do, and this has been working ok until I was openGL for graphics, specifically the gl_FragCoord function, which yields results like this (on a windows machine, the shape is perfectly centred and the correct size) enter image description here

I usually just hardcode some values with trial and error to account for this scaling, but is there a way I can permanently fix this for all programs?

Sorry for the long question and thanks in advance for any answers!

(edit) Also im preferrably looking for a programmatic way to account for this scaling rather than using software like switchresx to force the display on native res as that makes the mac almost unusable.

CodePudding user response:

Have you tried:

W, H =pygame.display.get_desktop_sizes()

Although your screen may have nominal a resolution of 2560 x 1600 pixels, the program may not recognize that resolution. I would verify that the pixel coordinates being passed correlate to the coordinates that the program recognizes.

So let's say for W you get a value other than 2560, then you know the scaling factor and can adjust accordingly.

I have a feeling that this has to do with the Retina display itself more than the OS. My guess is that with the Retina display you have what I'm going to refer to colloquilally as 'subpixels'. So, for each pixel your program is identifying you have several 'subpixels' which add up to your nominal resolution of 2560 x 1600, while pygame only "sees" lets say 1680x1050 pixel blocks, each of which contain 'x' Retina display 'subpixels'.

If getting the desktop size returns your nominal display value, try using this code to physically measure your display size:

import pygame as pg

MAIN = pg.display.set_mode((0, 0), pg.FULLSCREEN)


def GameUI(hrange, wrange):

    for h in range(hrange):

        if h % 10 != 0:
            pg.draw.rect(MAIN,(255, 255, 255), (5,h,1,1))
        elif h % 100 == 0:
            pg.draw.rect(MAIN, (255, 255, 255), (5, h, 20, 1))  # draws long tick at intervals of 100
        elif h % 10 == 0:
            pg.draw.rect(MAIN, (255, 255, 255), (5, h, 10, 1))  # draws long tick at intervals of 10


    for w in range(wrange):

        if w % 10 != 0:
            pg.draw.rect(MAIN,(255, 255, 255), (w, 5, 1, 1))
        elif w % 100 == 0:
            pg.draw.rect(MAIN, (255, 255, 255), (w, 5, 1, 20))  # draws long tick at intervals of 100
        elif w % 10 == 0:
            pg.draw.rect(MAIN, (255, 255, 255), (w, 5, 1, 10))  # draws long tick at intervals of 10

    pg.display.update()

def Main():

    run = True

    # pick some value larger than your resoultion
    hrange = 5000
    wrange = 5000

    while run:

        for event in pg.event.get():
            if event.type == pg.KEYDOWN:
                if event.key == pg.K_ESCAPE:
                    run = False

        GameUI(hrange, wrange)


if __name__ == "__main__":
    Main()

This should yeild the pixel resolution that the program recognises, it will at the very least take out the guesswork for you.

A couple other workarounds here are using Width = 0 Height = 0 and pygame.FULLSCREEN to automatically set the size to your screen:

MAIN = pygame.display.set_mode((0, 0), pg.FULLSCREEN)

You could also, theoretically, use pygame.display.get_window_size() to see if it matches your nominal resolution OR your measured resolution. And if its the latter, then you have an easy fix of comparing:

W, H =pygame.display.get_desktop_sizes() to pygame.display.get_window_size()

This is my first answer on StackOverflow so if I'm not entirely on the mark here please be kind <3

Edit:

Here is something that might be useful: How to find display scaling factor on retina/4k displays?

  • Related