Skip to content

Make windows on non-default displays follow their display's configuration - #11566

Open
utzcoz wants to merge 2 commits into
robolectric:masterfrom
utzcoz:multi-display-configuration
Open

utzcoz wants to merge 2 commits into
robolectric:masterfrom
utzcoz:multi-display-configuration

Conversation

@utzcoz

@utzcoz utzcoz commented Oct 8, 2026

Copy link
Copy Markdown
Member

Robolectric can launch an activity on a display other than the default one, but it didn't treat that display as the source of the window's configuration:

  • On S and later, an activity launched with ActivityOptions#setLaunchDisplayId was laid out at that display's size, but its Configuration and WindowMetrics were the default display's. Window contexts and presentations on that display had the same problem.
  • ShadowDisplayManager.changeDisplay and removeDisplay only updated the display and notified display listeners. The windows on it kept their old configuration.

This PR makes Robolectric do what the window manager does on a device in both cases. It adds no public API: tests keep using ShadowDisplayManager.addDisplay, changeDisplay and removeDisplay, ActivityOptions#setLaunchDisplayId, Context#createWindowContext and Presentation.

@utzcoz

utzcoz commented Oct 8, 2026

Copy link
Copy Markdown
Member Author

I hope it can receive at least two approvals before merging.

@utzcoz

utzcoz commented Oct 9, 2026

Copy link
Copy Markdown
Member Author

Will fix CI tonight.

@utzcoz
utzcoz force-pushed the multi-display-configuration branch from 93f589c to c548373 Compare October 9, 2026 16:03
An activity launched on a non-default display was laid out at that
display's size, but on S and later its Configuration and WindowMetrics
were the default display's. Window contexts and presentations on that
display had the same problem.

On a device the window manager supplies these, and Robolectric now
does the same:

- an activity on another display gets that display's size, density,
  orientation and window bounds as its override configuration, keeps
  them through configurationChange(), and stays on the display when
  recreated
- the fake window manager service answers a window context's attach
  call with the configuration of its display
- the configuration a window is sent with its frame is that of its
  display. On SDK 37 a window context follows the configuration of its
  window, so a presentation fell back to the default display's
  configuration and size when it was shown

On SDK 37 a window context's theme exists before that configuration
arrives, so moving the theme onto the new resources needs
AssetManager.nativeThemeRebase, which Robolectric did not implement. It
now does, the way Theme::Rebase does natively.

New shared tests under android.server.wm in ctesque check on an
emulator and on Robolectric that an activity, a window context and a
presentation on a virtual display have that display's configuration and
size. They follow CTS's MultiDisplayActivityLaunchTests,
MultiDisplayClientTests, WindowContextTests and PresentationTest.

Signed-off-by: utzcoz <utzcoz@outlook.com>
Changing or removing a display only updated the display and notified
display listeners. The windows on it kept their old configuration.

Robolectric now does what the window manager does on a device:

- changing a non-default display gives the activities and window
  contexts on it the display's new configuration. An activity that
  doesn't handle the change is recreated. The windows that stay on the
  display, such as those of an activity that handles the change and of
  a presentation, are resized
- removing a display moves the activities on it to the default
  display. One that handles the change stays, and receives
  onMovedToDisplay and the configuration it has there. One that
  doesn't is recreated there. The content of a private display, such
  as a virtual display that isn't public, is destroyed with it

The configuration of the default display stays the global one, which
setQualifiers changes along with the display.

An activity on another display also keeps that display's size when the
global configuration changes under ActivityScenario, and gets the
display's metrics from configurationChange(). One that handles a
change gets the new size from Display#getSize too.

The shared tests under android.server.wm in ctesque check on an
emulator and on Robolectric that resizing a virtual display recreates
or resizes the activity on it, updates a window context and resizes a
presentation on it, and that releasing it destroys the activity and
dismisses the presentation. They follow CTS's MultiDisplayPolicyTests,
WindowContextTests and PresentationTest.

Signed-off-by: utzcoz <utzcoz@outlook.com>
@utzcoz
utzcoz force-pushed the multi-display-configuration branch from c548373 to 5baae36 Compare October 9, 2026 16:55
@utzcoz

utzcoz commented Oct 10, 2026

Copy link
Copy Markdown
Member Author

It's ready for reviewing now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant