Wandering Thoughts archives

2023-02-18

The size of a window is complicated in X (or can be)

A simple model of the size of windows and how they can be resized is that windows have a size in pixels and they can be resized pixel by pixel. Okay, you probably want to make it so that windows can have a minimum and a maximum size, because not everything can sensibly be made arbitrarily small or large (if you set the minimum and the maximum the same, your window is implicitly not resizable). However, windows in X can be more complicated than that, as I sort of mentioned in passing in yesterday's entry on implementing 'grow down' window placement in Fvwm.

At the level of the X protocol, windows have a size in pixels and that's it. However, X has long had a way for programs to tell the window manager that they should only be sized and resized in fixed pixel sized amounts, not resized to arbitrary pixels. You can look at this information with the xprop program; you want the WM_NORMAL_HINTS property, which is described in the Xlib programming manual section 14.1.7 and section 4.1.2.3 of the Inter-Client Communication Conventions Manual.

A major use of these quantized sizes is for terminal programs to tell the window manager that they should only be resized in units of whole characters. For example, an xterm window for me reports (among other things):

program specified size: 1309 by 796
program specified minimum size: 45 by 37
program specified resize increment: 16 by 33
program specified base size: 29 by 4

Here, 16x33 is roughly the character size, and the base size of 29x4 accounts for the scroll bar and some padding. If I take the program specified size (which is in pixels), subtract the base size, and divide by the resize increment, I get 80x24. Not coincidentally, if I started to resize this window, my window manager would report its size as '80x24', not '1309x796'.

These days, there's another surprising but potentially common place that you can encounter this quantization. Here is xprop output from Firefox:

program specified minimum size: 900 by 240
program specified maximum size: 16384 by 16384
program specified resize increment: 2 by 2
program specified base size: 900 by 240

I'm using a 4K display that Firefox considers 'HiDPI'. Firefox on HiDPI displays doubles the size of 'CSS pixels' so that people who do things like set set '10 px' font sizes don't create microscopic text (cf; Firefox also generally scales up images and so on). When Firefox doubles the size of CSS pixels, it quite reasonably decides that it should be resized in 2x2 increments, rather than pixel by pixel.

(Chrome doesn't do this on my HiDPI display, and I started up Chrome for the first time in months just to check this.)

This has the interesting side effect that if I resize a Firefox window, the 'window size' my window manager reports is not at all the size in pixels of the actual window. A Firefox window that is physically 2466 pixels by 1614 pixels can be reported as being '783 by 687'; this comes from subtracting the base size from the pixel size, then dividing by two in each direction.

Other programs that are automatically HiDPI aware can also behave this way. Based on checking some GTK based applications (such as Liferea), I believe that all HiDPI aware GTK applications set their resize increment to 2x2 by default. Many laptop screens are HiDPI these days, so people using Linux desktops on them may have seen this happening without realizing. Alternately, desktop environments may either omit reporting window sizes during resize entirely or not scale them if the resize increment is too low. This is generally sensible behavior; most users don't care about the exact pixel size of random windows, whereas they may well care about the character size of terminal windows.

(Cinnamon on a non HiDPI display doesn't report a window size for Firefox when I resize it, but does report one for a terminal window.)

As a side note, xterm and some other programs allow you to specify their geometry in characters instead of in pixels, so that 'xterm -geometry 100x40' means a 100 character by 40 character xterm window, not a 100 pixel by 40 pixel one. I haven't looked to see if this is automatically handled in the X client libraries as part of setting the base size and resize increment, or whether it's handled separately.

PS: Since running terminal windows has always been important to X, I suspect that some version of this was in X10, if not even earlier versions of X. Resizing your terminal window in character units, not pixel units, is an obviously attractive thing.

unix/XWindowSizeComplicated written at 22:22:08; Add Comment


Page tools: See As Normal.
Search:
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.