mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-03-13 18:43:52 -05:00

In GTK 3.10 and above, high-DPI support is arranged by each window having a property called a 'scale factor', which translates logical pixels as seen by most of the GTK API (widget and window sizes and positions, coordinates in the "draw" event, etc) into the physical pixels on the screen. This is handled more or less transparently, except that one side effect is that your Cairo-based drawing code had better be able to cope with that scaling without getting confused. PuTTY's isn't, because we do all our serious drawing on a separate Cairo surface we made ourselves, and then blit subrectangles of that to the window during updates. This has two bad consequences. Firstly, our surface has a size derived from what GTK told us the drawing area size is, i.e. corresponding to GTK's _logical_ pixels, so when the scale factor is (say) 2, our drawing takes place at half size and then gets scaled up by the final blit in the draw event, making it look blurry and unpleasant. Secondly, those final blits seem to end up offset by half a pixel, so that a second blit over the same subrectangle doesn't _quite_ completely wipe out the previously blitted data - so there's a ghostly rectangle left behind everywhere the cursor has been. It's not that GTK doesn't _let_ you find out the scale factor; it's just that it's in an out-of-the-way piece of API that you have to call specially. So now we do: our backing surface is now created at a pixel resolution matching the screen's real pixels, and we translate GTK's scale factor into an ordinary cairo_scale() before we commence drawing. So we still end up drawing the same text at the same size - and this strategy also means that non-text elements like cursor outlines and underlining will be scaled up with the screen DPI rather than stubbornly staying one physical pixel thick - but now it's nice and sharp at full screen resolution, and the subrectangle blits in the draw event are back to affecting the exact set of pixels we expect them to. One silly consequence is that, immediately after removing the last one, I've installed a handler for the GTK "configure-event" signal! That's because the GTK 3 docs claim that that's how you get notified that your scale factor has changed at run time (e.g. if you reconfigure the scale factor of a whole monitor in the GNOME settings dialog). Actually in practice I seem to find out via the "draw" event before "configure" bothers to tell me, but now I've got a usefully idempotent function for 'check whether the scale factor has changed and sort it out if so', I don't see any harm in calling it from anywhere it _might_ be useful.