Skip to content

NSScreen: keep the visible frame out of the area the server reserves - #953

Open
probonopd wants to merge 1 commit into
gnustep:masterfrom
probonopd:fix-nsscreen-visible-frame-work-area
Open

probonopd wants to merge 1 commit into
gnustep:masterfrom
probonopd:fix-nsscreen-visible-frame-work-area

Conversation

@probonopd

@probonopd probonopd commented Sep 20, 2026 •

Copy link
Copy Markdown
Contributor

This is the libs-gui half of the paired change discussed in gnustep/libs-back#217: the backend reports the area the window manager leaves to application windows, and -[NSScreen visibleFrame] is built from it.

-visibleFrame takes the whole screen and subtracts the menu bar, so it ignores the space a panel or a dock reserves, and an application that places a window in the visible frame puts it under whatever else is on the screen.

GSDisplayServer -workAreaForScreen: answers that area, an empty rect when the server knows of none, in which case -visibleFrame behaves exactly as before. A reservation is counted once, as @rfm asked for in #217: where the area is already shorter than the screen at the top, that much is taken off the menu bar height rather than subtracted again, so a menu bar that reserves its own strip with the window manager does not cost twice its height.

On an 800x600 screen whose window manager reserves the lower 128 pixels and a 22 pixel strip at the top for the menu bar (_NET_WORKAREA = 0, 22, 800, 450, which the X11 backend already reads):

$ ./sprobe                      # upstream master
frame        0 0 800 600
workArea     0 128 800 450
visibleFrame 0 0 800 578        # the dock is ignored

$ ./sprobe                      # with this change
frame        0 0 800 600
workArea     0 128 800 450
visibleFrame 0 128 800 450      # the menu bar strip is not taken off twice

With nothing reserved (_NET_WORKAREA equal to the screen) both builds give 0 0 800 578, the menu bar height coming off as before.

$ cd Tests && gnustep-tests gui/NSScreen          # upstream master
Failed test:     visibleFrame.m:57 ... the visible frame keeps out of it in both directions
Failed test:     visibleFrame.m:64 ... a menu bar the server has already reserved is not taken off twice

$ cd Tests && gnustep-tests gui/NSScreen          # with this change
      6 Passed tests
All OK!

The test skips itself where the display server reserves nothing, so a bare server without a window manager is not asked to produce a work area.

The backend half is gnustep/libs-back#217, which needs gnustep/libs-back#226 under it; the two can be merged together.

cc @pkgdemon

probonopd added a commit to gershwin-desktop/gershwin-developer that referenced this pull request Sep 20, 2026
…menu bar

-[NSScreen visibleFrame] took the whole screen and subtracted the menu
bar, so it ignored whatever else reserves space on the screen: an
application that placed a window in the visible frame put it under the
Dock.  GSDisplayServer now answers -workAreaForScreen: with the area the
display server leaves to application windows, which the X11 backend takes
from _NET_WORKAREA, and the visible frame starts from that area.  A
display server that knows of no such area answers an empty rect and the
visible frame is what it was, so nothing that lacks the backend side
changes behaviour or raises.

Submitted upstream as gnustep/libs-gui#953.
-[NSScreen visibleFrame] took the whole screen and subtracted the menu bar,
so it ignored the space a panel or a dock reserves.  An application placing
a window in the visible frame put it under whatever else is on the screen.

GSDisplayServer answers -workAreaForScreen: with the area left to
application windows, an empty rect when it knows of none, and -visibleFrame
starts from that area instead of the whole screen.  A display server that
does not implement the method behaves as before.

A reservation is counted once: where the area is already shorter than the
screen at the top, that much is taken off the menu bar height rather than
subtracted a second time, so a menu bar that reserves its own strip with
the window manager does not cost twice its height.

On X11 the area comes from _NET_WORKAREA, which the backend already reads.
With a work area of 0 128 800 450 on an 800x600 screen and a 22 high menu
bar standing in the reserved strip, -visibleFrame was 0 0 800 578 and is
now 0 128 800 450.
@probonopd
probonopd force-pushed the fix-nsscreen-visible-frame-work-area branch from 4f44efc to 5ad9bf6 Compare September 20, 2026 23:29
probonopd added a commit to probonopd/libs-back that referenced this pull request Sep 20, 2026
The frame of a screen was replaced by _NET_WORKAREA whenever there was a
single monitor, so NSScreen described what the window manager leaves over
rather than the display.  An application could not learn the geometry of
the monitor, and one that reserves space itself, a menu bar or a dock,
could not place itself in the strip it had just reserved, since that strip
lies outside every frame it can see.

The frame is the monitor again, the work area is kept beside it, and
-workAreaForScreen: answers it.  The other servers answer their whole
screen, which is what they reserve nothing of.

This is the backend half of the pair discussed in gnustep#217; the gui half,
which builds -[NSScreen visibleFrame] from the new method, is
gnustep/libs-gui#953.  It sits on top of gnustep#226, whose flip of the
_NET_WORKAREA origin and count of monitors rather than outputs it needs
and does not repeat.
probonopd added a commit to gershwin-desktop/gershwin-developer that referenced this pull request Sep 20, 2026
The patch that built the visible frame from the work area went on to
subtract the menu bar height from it, so where the window manager had
already reserved the menu bar's strip, as it does when the menu bar is a
window of its own, those pixels were taken off twice and applications were
told the screen was shorter than it is.  Only as much of the menu bar
height as the work area has not already been reduced by is taken off now.

Measured on an 800x600 screen with a 22 pixel menu bar at the top and a
dock at the bottom: the visible frame was 0 128 800 428 and is now
0 128 800 450, which is the work area itself.

Reviewers of gnustep/libs-gui#953 asked for exactly this; the pull request
carries the same change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant