The protocol seems to allow this, because it explicitly mentions either
session lock surface or compositor blanking the output in this sentence:
> The locked event must not be sent until a new "locked" frame
(either from a session lock surface or the compositor blanking the output)
has been presented on all outputs and no security sensitive normal/unlocked
content is possibly visible.
Since `locked_screen_delay` is capped to 5 seconds,
after the 5 seconds this timer is registered for, we assume that
all outputs are covered either by lockedead or by an actual lock frame.
Thus sending locked is ok.
After scaling m_captureBox from logical to pixel coordinates, the box may
have non-integer dimensions (e.g. logical 401x301 at scale 1.25 -> pixel
501.25x376.25). m_bufferSize is then computed as captureBox.size() and
sent to the client as int32 width/height (truncating the fraction), but
m_bufferSize itself stays as a fractional Vector2D.
When the client allocates the integer-sized buffer and submits it,
CScreenshareFrame::share() rejects it with ERROR_BUFFER_SIZE because
Vector2D::operator== is exact double comparison: (501, 376) != (501.25,
376.25). The frame is sent failed, and the client retries forever.
The SHARE_WINDOW path already rounds its bufferSize; the SHARE_REGION
path didn't. Round the captureBox immediately after scaling so all
downstream consumers (m_bufferSize, render translates) see clean integer
pixel coordinates.
Reproducer at scale 1.25 on a 1920x1080 monitor:
wf-recorder -g '500,200 401x301' -f /tmp/x.mp4
# "Failed to copy frame, retrying..." until exit
wf-recorder -g '500,200 400x300' -f /tmp/x.mp4
# works (400*1.25=500, 300*1.25=375, both integer)
* fix(screenshare): adjust session cleanup and event emission order
Revised the handling of `stoppedListener` initialization in
`getManagedSession` to ensure correct scoping and lifecycle management.
Updated the `stop` method in `CScreenshareSession` to adjust the order
of `screenshareEvents` and `stopped.emit()` to prevent potential
use-after-free scenarios.
* fix(screenshare): ensure managedSession removal uses consistent target reference
This change updates the lambda in the stopped listener to use
a pre-fetched target pointer for comparison when erasing sessions.
* fix(screenshare): use early-return and smart ptr comparison in session cleanup
* tests: Relax color management requirements in the colors test
This continues the work from d4dd299 (#14142):
- Fixes a missed check assuming a fixed value for `colorManagementPreset`
- Stricten checks to require that the expected keywords are present as json keys
* tests: Refactor `Tests::getAttribute` (was `Tests::getWindowAttribute`)
- Improve ergonomics by consistently handling attribute name;
- Remove 'window' from the function name, since it is compatible with
other responses too;
- Document the function.
* tests: Fix solitary test assuming it knows the complete set of blockers
The test was failing on the CI because new blockers appeared,
which were not expected by the text. Fix the test, so that it
just checks the set of expected blockers is a subset of actual
blockers
* hyprtester: Minor misc fixes
- Use `std::filesystem::path` instead of `std::string` in some places;
- Use `std::ranges::sort`, as suggested by clang-tidy;
- Reset colors at the end of every log line;
- Give more specific error messages in main.
* hyprtester: Fix a bug in `hyprlandAlive()`
Successful standard library calls are permitted to (and do) modify the
value of `errno` arbitrarily. Checking the value of `errno` only makes
sense when the library function returns an error. So, the correct
condition of a successful signal delivery is that the call to `kill`
returns 0.
Btw, given the possible other error values of `kill(2)`, should we even
consider `errno` at all?
* hyprtester: Restructure main
Split main's `main()` into multiple functions, separate responsibilities
more cleanly.
Add default values for cmd-line options to the help message.
* hyprtester: Remove redundant path canonicalization
* hyprtester: Run unified clean up code before every test
* tests: Use RAII for clients in client tests
Turn clients in client tests into classes. Constructors
initialize, destructors deinitialize.
Not only is it better design when entities (clients) are
modeled as classes, keeping all the methods connected,
this also ensures the tests perform their custom cleanup.
This will be especially important when we introduce early
termination on failure into the tests.
* hyprtester: Rewrite the testing framework!
- Implement a new test definition system used via the `TEST_CASE` and
`SUBTEST` macros.
- Adds `ASSERT*` and reimplements `EXPECT*` macros. The former now
terminate the test immediately. Also add some new macros, such as
`FAIL_TEST`.
- Move existing tests to the new system. For trivial cases, break
existing test functions down to multiple test cases.
- For non-trivial cases and a few other possible improvements, leave
TODOs.
* tests: Use `EXPECT*` instead of `ASSERT*` in some places
`ASSERT*` macros terminate the test as soon as they fail. They are
appropriate to use when, if something fails, the rest of the test
does not make sense and more error messages from failing checks will
just pollute the output.
`EXPECT*` macros mark the test as failed but its execution continues.
It makes sense to use them when error messages from the following checks
in the test may be useful for someone who will be reading the log.
I changed some uses of `ASSERT*` in main tests to `EXPECT*`. But I was
not reading tests very carefully, so maybe I was wrong in some places.
My rule of thumb was:
- Checks that ensure that a kitty opens / a certain set/number of
windows exists are fatal;
- A series of checks, especially on the same string returned by
`Hyprland`, are non-fatal;
- Checks in tests with tightly coupled steps (i.e., do this, check,
do this with the result of the previous step, check, etc) are fatal.