Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 9e5059ee0714d223f2a461b40c35cfb5ceffd99f
https://github.com/WebKit/WebKit/commit/9e5059ee0714d223f2a461b40c35cfb5ceffd99f
Author: Aditya Keerthi <[email protected]>
Date: 2026-10-14 (Wed, 14 Oct 2026)
Changed paths:
M Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml
M Source/WebCore/CMakeLists.txt
M Source/WebCore/DerivedSources-input.xcfilelist
M Source/WebCore/DerivedSources-output.xcfilelist
M Source/WebCore/DerivedSources.make
M Source/WebCore/Headers.cmake
M Source/WebCore/Sources.txt
M Source/WebCore/WebCore.xcodeproj/project.pbxproj
M Source/WebCore/bindings/js/WebCoreBuiltinNames.h
M Source/WebCore/css/parser/CSSParserContext.cpp
M Source/WebCore/css/parser/CSSParserContext.h
M Source/WebCore/css/parser/CSSSubstitutionParser.cpp
M Source/WebCore/css/query/MediaQueryFeatures.cpp
M Source/WebCore/css/query/MediaQueryFeatures.h
M Source/WebCore/css/query/MediaQueryParser.cpp
A Source/WebCore/page/DOMWindow+Viewport.idl
M Source/WebCore/page/DOMWindow.cpp
M Source/WebCore/page/DOMWindow.h
M Source/WebCore/page/LocalDOMWindow.cpp
M Source/WebCore/page/LocalDOMWindow.h
M Source/WebCore/page/LocalFrameView.cpp
M Source/WebCore/page/Page.cpp
M Source/WebCore/page/Page.h
A Source/WebCore/page/Viewport.cpp
A Source/WebCore/page/Viewport.h
A Source/WebCore/page/Viewport.idl
A Source/WebCore/page/ViewportSegments.h
M Source/WebCore/style/StyleEnvironmentVariables.cpp
M Source/WebCore/style/StyleEnvironmentVariables.h
M Source/WebCore/style/StyleSubstitutionResolver.cpp
M Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in
M Source/WebKit/Shared/WebPageCreationParameters.h
M Source/WebKit/Shared/WebPageCreationParameters.serialization.in
M Source/WebKit/UIProcess/WebPageProxy.cpp
M Source/WebKit/UIProcess/WebPageProxy.h
M Source/WebKit/UIProcess/WebPageProxyInternals.h
M Source/WebKit/UIProcess/ios/WKContentView.mm
M Source/WebKit/WebProcess/WebPage/WebPage.cpp
M Source/WebKit/WebProcess/WebPage/WebPage.h
M Source/WebKit/WebProcess/WebPage/WebPage.messages.in
Log Message:
-----------
Implement the Viewport Segments API
https://bugs.webkit.org/show_bug.cgi?id=327042
rdar://187132619
Reviewed by Abrar Rahman Protyasha, Richard Robinson, and Tim Nguyen.
The Viewport Segments API allows developers to access the position and
dimensions of logically separate viewport segments. For example, when a foldable
device is unfolded, a page can use the API to lay out content on either side of
the fold, rather than across it.
The API comprises:
- The `horizontal-viewport-segments` and `vertical-viewport-segments` media
features, which expose the number of segments in each direction.
- The `viewport-segment-{width,height,top,right,bottom,left}` environment
variables, which take two integer indices (column, row) and expose the
position and dimensions of each segment.
- `window.viewport.segments`, which returns an array of DOMRect objects
representing the position and dimensions of each segment.
Spec: https://drafts.csswg.org/css-env-1/#viewport-segments
https://drafts.csswg.org/mediaqueries-5/#mf-horizontal-viewport-segments
https://drafts.csswg.org/css-viewport/#segments
Segments are represented by a new `ViewportSegments` struct, which holds the
number of columns and rows, and the rect of each segment. The UI process
computes the segments and sends them to the web process, where they are stored
on the `Page`. When the segments change, the `Page` updates the environment
variables, re-evaluates media queries, and invalidates the segments cached by
each `Viewport` object.
On iOS, segments are computed from the division regions vended by
`-[UIView reservedRegionsOfKind:]`. The margin around each region is removed,
so that the fold is treated as a rect with zero dimension in one axis, and the
resulting segments are continuous. In the future, fold margins could be exposed
as a separate API, pending CSSWG discussion.
When the viewport is not segmented, both media features evaluate to 1, the
environment variables are undefined, and `window.viewport.segments` contains a
single rect matching the size of the visual viewport.
The API is disabled by default, behind the ViewportSegmentsAPIEnabled
preference.
Tests to come in a separate change.
* Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml:
Add a testable preference for the API, disabled by default.
* Source/WebCore/CMakeLists.txt:
* Source/WebCore/DerivedSources-input.xcfilelist:
* Source/WebCore/DerivedSources-output.xcfilelist:
* Source/WebCore/DerivedSources.make:
* Source/WebCore/Headers.cmake:
* Source/WebCore/Sources.txt:
* Source/WebCore/WebCore.xcodeproj/project.pbxproj:
* Source/WebCore/bindings/js/WebCoreBuiltinNames.h:
* Source/WebCore/css/parser/CSSParserContext.cpp:
(WebCore::CSSParserContext::CSSParserContext):
(WebCore::add):
* Source/WebCore/css/parser/CSSParserContext.h:
Add a bit for the preference, so that segment indices are only accepted when
the API is enabled.
* Source/WebCore/css/parser/CSSSubstitutionParser.cpp:
(WebCore::isValidEnvReference):
Require two numbers after a `viewport-segment-*` name. Other names, and all
names when the API is disabled, still may not be followed by numbers.
* Source/WebCore/css/query/MediaQueryFeatures.cpp:
(WebCore::MQ::Features::horizontalViewportSegmentsFeatureSchema):
(WebCore::MQ::Features::verticalViewportSegmentsFeatureSchema):
Report the number of columns and rows, respectively. Evaluate to unknown when
the API is disabled.
(WebCore::MQ::Features::horizontalViewportSegments):
(WebCore::MQ::Features::verticalViewportSegments):
(WebCore::MQ::Features::allSchemas):
* Source/WebCore/css/query/MediaQueryParser.cpp:
(WebCore::MQ::MediaQueryParser::schemaForFeatureName):
* Source/WebCore/css/query/MediaQueryFeatures.h:
* Source/WebCore/page/DOMWindow+Viewport.idl: Added.
* Source/WebCore/page/DOMWindow.cpp:
(WebCore::DOMWindow::viewport):
Throw a SecurityError for remote windows, matching `visualViewport`.
* Source/WebCore/page/DOMWindow.h:
* Source/WebCore/page/LocalDOMWindow.cpp:
(WebCore::LocalDOMWindow::viewport):
Create the `Viewport` lazily.
* Source/WebCore/page/LocalDOMWindow.h:
* Source/WebCore/page/LocalFrameView.cpp:
(WebCore::LocalFrameView::layoutOrVisualViewportChanged):
Invalidate the cached segments, since the single segment reported when the
viewport is not segmented matches the size of the visual viewport.
* Source/WebCore/page/Page.cpp:
(WebCore::Page::setViewportSegments):
Update the environment variables and re-evaluate media queries in each
document, as is done when the device posture changes, then invalidate the
cached segments.
* Source/WebCore/page/Page.h:
* Source/WebCore/page/Viewport.cpp: Added.
(WebCore::Viewport::Viewport):
(WebCore::Viewport::segments const):
Cache the DOMRect objects, so that the same objects are returned until the
segments are invalidated.
(WebCore::Viewport::invalidateSegments):
* Source/WebCore/page/Viewport.h: Added.
* Source/WebCore/page/Viewport.idl: Added.
* Source/WebCore/page/ViewportSegments.h: Added.
(WebCore::operator<<):
Store the rects in row-major order. A single column and row, the default,
means that the viewport is not segmented.
* Source/WebCore/style/StyleEnvironmentVariables.cpp:
(WebCore::Style::EnvironmentVariables::setValueForName):
Add a way to set variables whose names are not known ahead of time, unlike the
`UADefinedVariable` cases.
(WebCore::Style::EnvironmentVariables::buildValues):
(WebCore::Style::EnvironmentVariables::updateViewportSegmentVariables):
Store each value under a name that includes the segment indices, for example
"viewport-segment-width 1 0". Remove the existing segment variables first,
since the number of segments may have changed. When the viewport is not
segmented, leave the variables undefined, so that the fallback is used.
(WebCore::Style::EnvironmentVariables::didChangeViewportSegments):
* Source/WebCore/style/StyleEnvironmentVariables.h:
* Source/WebCore/style/StyleSubstitutionResolver.cpp:
(WebCore::Style::SubstitutionResolver::substituteEnvFunction):
Consume the indices following a `viewport-segment-*` name, and append them to
the name to look up the variable.
* Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in:
* Source/WebKit/Shared/WebPageCreationParameters.h:
* Source/WebKit/Shared/WebPageCreationParameters.serialization.in:
Send the current segments when creating a page, so that a new web process
starts with the correct segments.
* Source/WebKit/UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::creationParameters):
(WebKit::WebPageProxy::setViewportSegments):
Store the segments, and send them to the web process only when they change and
there is a running process.
* Source/WebKit/UIProcess/WebPageProxy.h:
* Source/WebKit/UIProcess/WebPageProxyInternals.h:
* Source/WebKit/UIProcess/ios/WKContentView.mm:
(-[WKContentView layoutSubviews]):
(-[WKContentView _updateViewportSegments]):
Treat a fold narrower than 1pt as a vertical fold, which separates columns, and
a fold shorter than 1pt as a horizontal fold, which separates rows. Other
regions are ignored. Each segment spans the space between adjacent folds, or
between a fold and the edge of the view.
* Source/WebKit/WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::WebPage):
(WebKit::WebPage::setViewportSegments):
* Source/WebKit/WebProcess/WebPage/WebPage.h:
* Source/WebKit/WebProcess/WebPage/WebPage.messages.in:
Canonical link: https://commits.webkit.org/323738@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications