Skip to content

feat(macOS): libdispalydevice integration#5338

Open
martona wants to merge 3 commits into
LizardByte:masterfrom
martona:integrate-macos-libdisplaydevice
Open

feat(macOS): libdispalydevice integration#5338
martona wants to merge 3 commits into
LizardByte:masterfrom
martona:integrate-macos-libdisplaydevice

Conversation

@martona

@martona martona commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Description

This is a follow-up from last week's libdisplaydevice work: macOS integration in Sunshine.

macOS now uses libdisplaydevice for display enumeration as well as applying/reverting changes.

I also removed the patch that kept the display awake; Sunshine now relies on the new libdisplaydevice functionality to do the same. Note that while libdisplaydevice gained the ability to wake displays on Windows, this PR does not take advantage of it; the scope was kept to macOS.

I had to bump the libdisplaydevice submodule.

Screenshot

Issues Fixed or Closed

Roadmap Issues

Type of Change

  • feat: New feature (non-breaking change which adds functionality)
  • fix: Bug fix (non-breaking change which fixes an issue)
  • docs: Documentation only changes
  • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semicolons, etc.)
  • refactor: Code change that neither fixes a bug nor adds a feature
  • perf: Code change that improves performance
  • test: Adding missing tests or correcting existing tests
  • build: Changes that affect the build system or external dependencies
  • ci: Changes to CI configuration files and scripts
  • chore: Other changes that don't modify src or test files
  • revert: Reverts a previous commit
  • BREAKING CHANGE: Introduces a breaking change (can be combined with any type above)

Checklist

  • Code follows the style guidelines of this project
  • Code has been self-reviewed
  • Code has been commented, particularly in hard-to-understand areas
  • Code docstring/documentation-blocks for new or existing methods/components have been added or updated
  • Unit tests have been added or updated for any new or modified functionality

AI Usage

  • None: No AI tools were used in creating this PR
  • Light: AI provided minor assistance (formatting, simple suggestions)
  • Moderate: AI helped with code generation or debugging specific parts
  • Heavy: AI generated most or all of the code changes

@ReenigneArcher

ReenigneArcher commented Jun 26, 2026

Copy link
Copy Markdown
Member

Apologies, but I merged a change a little while ago that causes conflicts with this one.

@martona martona force-pushed the integrate-macos-libdisplaydevice branch from ede0ab1 to b733db8 Compare June 26, 2026 03:39
@martona

martona commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

No worries, should merge cleanly now.

Comment thread src/display_device.cpp Outdated
Comment thread src/display_device.cpp
martona and others added 3 commits June 26, 2026 20:04
Co-authored-by: Dave Lane <42013603+ReenigneArcher@users.noreply.github.com>
@ReenigneArcher ReenigneArcher force-pushed the integrate-macos-libdisplaydevice branch from 6c46fdc to 5700431 Compare June 27, 2026 00:04
@sonarqubecloud

Copy link
Copy Markdown

@codecov

codecov Bot commented Jun 27, 2026

Copy link
Copy Markdown

Bundle Report

Bundle size has no change ✅

Comment thread src/display_device.cpp
#endif
}

std::unique_ptr<DisplayPowerInterface> make_display_power() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't this added for Windows as well?

https://github.com/LizardByte/libdisplaydevice/blob/65616076ba881046085438c80fddead9beedf74f/src/windows/display_power.cpp#L43

Also, found this which should maybe replaced with the new library code?

// Keep the display awake during capture. If the display goes to sleep during
// capture, best case is that capture stops until it powers back on. However,
// worst case it will trigger us to reinit DD, waking the display back up in
// a neverending cycle of waking and sleeping the display of an idle machine.
SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
auto clear_display_required = util::fail_guard([]() {
SetThreadExecutionState(ES_CONTINUOUS);
});

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that's what I meant in part when I said I could make a power management pass after the interface-factories. Technically it could have been a part of this PR, but I did not want it out of control, touching multiple OSes. A note regarding it is also in the body text of the PR: it's definitely not forgotten about, it just felt out of scope.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Obviously, I have a reading problem today. Thanks for the clarification!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just throw a couple TODO comments in? (Sonar will complain about the TODOs, but I'll bypass it)

@codecov

codecov Bot commented Jun 27, 2026

Copy link
Copy Markdown

❌ 2 Tests Failed:

Tests completed Failed Passed Skipped
346 2 344 4
View the top 2 failed test(s) by shortest run time
DisplayDeviceConfigTest/ParseHdrOption::IntegrationTest/2
Stack Traces | 0s run time
.../tests/unit/test_display_device.cpp:122
Expected equality of these values:
  std::get<display_device::SingleDisplayConfiguration>(result).m_hdr_state
    Which is: (nullopt)
  expected_value
    Which is: (4-byte object <01-00 00-00>)
DisplayDeviceConfigTest/ParseHdrOption::IntegrationTest/3
Stack Traces | 0s run time
.../tests/unit/test_display_device.cpp:122
Expected equality of these values:
  std::get<display_device::SingleDisplayConfiguration>(result).m_hdr_state
    Which is: (nullopt)
  expected_value
    Which is: (4-byte object <00-00 00-00>)

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@martona

martona commented Jun 27, 2026

Copy link
Copy Markdown
Contributor Author

Everything going red is on libdisplaydevice. EnumeratedDevice is an aggregate and does not define a constructor, so calls like:

devices.emplace_back(device_id, display_name, friendly_name, edid, info);

rely on C++20 parenthesized aggregate initialization through std::construct_at. Newer toolchains accept that, which is why it built for me locally, but the Xcode 15.4 CI toolchain rejects it here.

The cleanest fix is to go back to libdisplaydevice and undo the SONAR fix that caused this by changing the affected EnumeratedDevice insertions back to explicit braced aggregate construction, e.g. push_back(EnumeratedDevice { ... }). I'll submit a PR for that, then update the Sunshine submodule pin.

Before I do that though... does this sound like the best course of action to you too?

@ReenigneArcher

ReenigneArcher commented Jun 27, 2026

Copy link
Copy Markdown
Member

Everything going red is on libdisplaydevice. EnumeratedDevice is an aggregate and does not define a constructor, so calls like:

devices.emplace_back(device_id, display_name, friendly_name, edid, info);

rely on C++20 parenthesized aggregate initialization through std::construct_at. Newer toolchains accept that, which is why it built for me locally, but the Xcode 15.4 CI toolchain rejects it here.

The cleanest fix is to go back to libdisplaydevice and undo the SONAR fix that caused this by changing the affected EnumeratedDevice insertions back to explicit braced aggregate construction, e.g. push_back(EnumeratedDevice { ... }). I'll submit a PR for that, then update the Sunshine submodule pin.

Before I do that though... does this sound like the best course of action to you too?

That sounds fine, maybe we should add an older macOS runner to the libdisplaydevice build/test matrix as well.

I think there's a few other things going on as well.

  1. Unused function on Linux... you can apply [[maybe_unused]]?
[34](https://github.com/LizardByte/Sunshine/actions/runs/28272130054/job/83772706710?pr=5338#step:6:2835)
Error: /home/runner/work/Sunshine/Sunshine/src/display_device.cpp:144:10: error: ‘bool display_device::{anonymous}::is_unsigned_integer(std::string_view)’ defined but not used [-Werror=unused-function]
  144 |     bool is_unsigned_integer(std::string_view value) {
      |          ^~~~~~~~~~~~~~~~~~~
  1. Two tests failing on macos-latest runners:
[ RUN      ] DisplayDeviceConfigTest/ParseHdrOption.IntegrationTest/2
/Users/runner/work/Sunshine/Sunshine/tests/unit/test_display_device.cpp:122: Failure
Expected equality of these values:
  std::get<display_device::SingleDisplayConfiguration>(result).m_hdr_state
    Which is: (nullopt)
  expected_value
    Which is: (4-byte object <01-00 00-00>)

[2026-06-27 01:07:15.242]: Tests: From /Users/runner/work/Sunshine/Sunshine/tests/unit/test_display_device.cpp:110
[2026-06-27 01:07:15.242]: Tests:   DisplayDeviceConfigTest/ParseHdrOption/IntegrationTest/2 started
[2026-06-27 01:07:15.242]: Info: Ignoring HDR display device request on macOS because macOS HDR changes are not supported by libdisplaydevice.
[2026-06-27 01:07:15.242]: Tests: At /Users/runner/work/Sunshine/Sunshine/tests/unit/test_display_device.cpp:122
[2026-06-27 01:07:15.242]: Tests:   Non-fatal failure: Expected equality of these values:
  std::get<display_device::SingleDisplayConfiguration>(result).m_hdr_state
    Which is: (nullopt)
  expected_value
    Which is: (4-byte object <01-00 00-00>)
[2026-06-27 01:07:15.242]: Tests: DisplayDeviceConfigTest/ParseHdrOption/IntegrationTest/2 failed
[  FAILED  ] DisplayDeviceConfigTest/ParseHdrOption.IntegrationTest/2, where GetParam() = ((4-byte object <01-00 00-00>, true), (4-byte object <01-00 00-00>)) (0 ms)
[ RUN      ] DisplayDeviceConfigTest/ParseHdrOption.IntegrationTest/3
/Users/runner/work/Sunshine/Sunshine/tests/unit/test_display_device.cpp:122: Failure
Expected equality of these values:
  std::get<display_device::SingleDisplayConfiguration>(result).m_hdr_state
    Which is: (nullopt)
  expected_value
    Which is: (4-byte object <00-00 00-00>)

[2026-06-27 01:07:15.242]: Tests: From /Users/runner/work/Sunshine/Sunshine/tests/unit/test_display_device.cpp:110
[2026-06-27 01:07:15.242]: Tests:   DisplayDeviceConfigTest/ParseHdrOption/IntegrationTest/3 started
[2026-06-27 01:07:15.242]: Info: Ignoring HDR display device request on macOS because macOS HDR changes are not supported by libdisplaydevice.
[2026-06-27 01:07:15.242]: Tests: At /Users/runner/work/Sunshine/Sunshine/tests/unit/test_display_device.cpp:122
[2026-06-27 01:07:15.242]: Tests:   Non-fatal failure: Expected equality of these values:
  std::get<display_device::SingleDisplayConfiguration>(result).m_hdr_state
    Which is: (nullopt)
  expected_value
    Which is: (4-byte object <00-00 00-00>)
[2026-06-27 01:07:15.242]: Tests: DisplayDeviceConfigTest/ParseHdrOption/IntegrationTest/3 failed
[  FAILED  ] DisplayDeviceConfigTest/ParseHdrOption.IntegrationTest/3, where GetParam() = ((4-byte object <01-00 00-00>, false), (4-byte object <00-00 00-00>)) (0 ms)

I didn't check every failure though, this was only a spot check.

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.

2 participants