Here is a patch that takes a slightly different approach than my previous one and fixes both fringe bitmaps and general image (including "widgets": checkboxes, arrows, etc) rendering in hidpi screens. I've attached a number of before/after screenshots. I added two new fields `scale_x` and `scale_y` to the frame struct. I believe going through the rif was overkilling in terms of indirections and in terms of legibility, specially if I wanted to implement independent scale factors for x and y in order to honour the previous implementation. Now it's simply f->scale_x and f->scale_y. These fields are initialized when the frame is created. They are floating point numbers, truncation or rounding is done after scaling. To be rigorous, these fields should belong to the terminal or to the display_info, because they're common to all frames in the terminal (indeed, they are closely related to resx and resy). But display_info structs are backend specific and adding macros or inlines to frame.h that reference them would have required including TERM_HEADER in many many places. Also, having them at the frame level is handy since scale factors are often, if not always, referenced in a context where a frame is at scope. The strategy is simple: scale fringe bitmaps and images geometries beforehand, so as to allow geometry calculations, but postpone actual scaling of the contents until the moment of their actual rendering to screen. The image module has a lot of image loading functions. In order to reduce the risk of regressions, I decided to adjust width and height at the end of each function, immediately before returning. Even if I've implemented this only for cairo (both with and without gtk), adding support for x without cairo and for w32 shouldn't be difficult at all. The ns backend simply sets both scale factors to 1, thus disabling scaling. Other unsupported backends now should at least carry better geometry computations, although contents won't be actually scaled. This doesn't support dynamic changes of dpi or scale factor. For two or three days (and their nights) I strived to get that working. I was able to catch xrandr resolution-change events, I was able to catch scale-change gtk notifications, but the assumption that everything is set just once at the beginning is firmly entrenched in the code. In particular, rescaling fonts on the fly turned out to be an insurmountable problem. I tried many, many things: clearing font caches, glyph caches, matrix caches, resetting the frame font parameter, remapping the default face (a la C-x C-+). I finally got it working but only for the default face, I could have gone and remapped also modeline faces, etc. I don't think such hacks are worth the price. In general, what people is doing to get x working with two monitors at different dpis is to set a common gtk scale factor that is good for the highest resolution screen (often = 2) and then scale the lowest resolution screen down using xrandr. This is an old hack now "officially" implemented in Ubuntu. So, if you launched an emacs frame in a hidpi laptop and then plugged an external monitor with the same or lower resolution, there won't be any problem. Otherwise, if your emacs frame started in the lowest resolution screen, then it should be scaled up, so the only way to go is to close it and open a frame afresh. Sorry for that. So, all in all, this fixes hidpi problems and should also work in the usual multi-monitor multi-dpi scenario. For a more comprehensive solution I see no other way than writing a modern gtk backend, which is also the way to move towards wayland. Best regards -- Carlos