* tokens: expire one shot initial workspace tokens
tokens are only removed once a window maps, so things like
xdg-desktop-portal got the 1337 month duration token added and always
first launch in the wrong workspace. check PINITIALWSTRACKING and if
mode 1 just give them a 1 second token. like other code paths does.
* tokens: increase timeout to 10 seconds
increase the timeout to 10 seconds, slow launching things like krita is
above the 1 second we have now. if 10 seconds is to much it can always
be fine tuned lower later.
* tokens: add a config option for timeout
add initial_workspace_token_timeout as a config option to be able to set
the default timeout for the initial workspace tracking token.
* tokens: rename timeout to actually timeout
urgl, to much going on at the same time. TIMEOUT certainly makes more
sense for an timeout.
* desktoå/view: fix IView virtual inheritance and erase_if ptr
CSubsurface and CSessionLock inherited IView non-virtually while
CWindow/CLayerSurface/CPopup inherited it virtually.
erase_if compared event.address with the derived complete object
pointer. under virtual inheritance those addresses differ.
* desktop/view: use dynamic casting over static casting
change to dynamic casting instead of static casting.
* better
* more better
more better is more.
---------
Co-authored-by: Vaxry <vaxry@vaxry.net>
* screenshare: don recopy a dmabuf while fence is pending
copy is called for every pending frame on the output commit. and output
commit fires on any output commit not just buffer ones. so the fence can
easily be not signaled yet.
* screenshare: erase done frames too
erase done frames from m_pendingFrames to avoid growing to huge
numbers. a finished frame copied/failed/session gone is skipped by the
copy but was only erased once it expired. a slow client could let the
vector grow.
after 254d6bae77 fadeouts now live in
fadingOutState() instead of the normal containers, so add SC_FADEOUT and
iterate the new fadingOutState() and block solitary for fadeouts.
glDrawBuffers is per FBO state, but it was only set when mirroring was
first enabled on whatever work buffer happened to be mainFB that frame.
since work buffers rotate other FBO's kept default single draw buffer.
move the draw buffer selection into internalAlloc so it always follows
the mirror attachment.
when lease is destroyed the destroy listener nullptr deref m_lease, and
all it uses it for is logging the fd number. capture the fd by value to
avoid crashing.
* dwindle: avoid crashing on expired weakptr
pTarget can be expired when toggling a tiled window to floating during a
drag move that triggers removeTarget -> recalculate -> calculateWorkspace
before the dead node has been cleaned up.
* hyprtester: wait for enabled monitor
without waiting for enabled monitor we can race the tests and call focus
on non enabled monitors.
* popup: fix crash on destroyed xdg surface resource
the xdg_surface can be destroyed before the xdg_popup, so CPopup::onDestroy
hasnt run yet and the popup is still in its parents m_children with m_wlSurface set.
if guard it in popupTreeExtents.
* popup: safe guard bad resource
popups can be fading out while the resource is dead, ifguard it and
return m_lastPos if thats the case.
* groups: add groupbar disable_when_only option
* groups: improve `groups` test
`groups_disable_when_only` test fails because it checks windows sizes after
`disable_when_only` option changed. Changing option currently don't
trigger window size update.
Same problem with `groups` test, but it worked because it or:
- didn't checked window size after changing option.
- called `hl.dsp.group.toggle()`, which trigger size update
- at the begining set `enable = 1` while it `== 1` by default
Now it fails too :D
Seems it works in usual Hyprland usage because:
- `CHyprGroupBarDecoration::draw` calls
- `g_pDecorationPositioner->repositionDeco(this)`,
which will invalidate cache and update sizes.
* groups: fix `disable_when_only` and `groups` tests
REFRESH_LAYOUTS is not required 'cause REFRESH_WINDOW_STATES will
trigger update of window position too.
* groups: fix groupbar drawing
use the current row and the SHM stride when calculating copy offsets,
the previous code calculated the copy offset incorrectly by always using
the first damaged row and by assuming each row as only as wide as the
damaged region.
* config: fix initial workspace tracking
previous refactor over to Executor missed m_isLaunchingExecOnce meaning
any hl.exec_cmd(hyprlauncher) got the token of 1337 month duration at
the first launched workspace, so the initial launch of things gets that
token and opens on the wrong workspace.
add m_isLaunchingExecOnce back, and make getHyprlandLaunchEnv a member
of CExecutor aswell.
the needle counting also missed the final partial chunk if the read
failed to read 512 bytes but still read a chunk.
* hyprtester: fix monitor rule
ID's are unreliable. try to parse it directly from name.
* core/output: don't destroy bound wl_output resources on same-name global replace
When a monitor is unplugged and replugged quickly (e.g. an external screen
losing power for a second), the new monitor's wl_output global replaces the
old defunct one in PROTO::outputs by name. Erasing the map entry destroyed
the old CWLOutputProtocol and, with it, every wl_output resource clients
still held. Clients processing the global_remove would then send
wl_output.release on an id the server had already destroyed, get
"invalid object N" posted on wl_display, and be fatally disconnected -
killing nearly every connected client (browsers, IMEs, shells, portals).
Repro (no hardware needed):
hyprctl output create headless test
# let any client bind it, then:
hyprctl --batch "output remove test ; output create headless test"
-> every client that bound the output is disconnected.
Fix: retire the old global instead of destroying it. It is removed from the
registry (removeGlobal) but kept alive in PROTO::defunctOutputs until every
client has released its resources; CWLOutputProtocol::destroyResource then
drains it. Resource destroy/release handlers now route through m_owner
instead of a name lookup so releases reach the defunct global they belong
to, and the self-erase on drain is identity-checked so a defunct global can
no longer erase the healthy same-name global that replaced it.
* core/output: clarify defunctOutputs comment
Reword per review: these globals are gone-but-not-yet-unref'd-by-all-clients,
not necessarily replaced.
* clang-format
* clang-format
---------
Co-authored-by: Titosy <dev.titosy@gmail.com>
Problem: The blurprepare intermediate used an 80-nit range but HDR
pixels can be much brighter. A 200-nit pixel was encoded as:
(200/80)^(1/2.2) = 1.52
which would get clamped to 1 causing clipping.
Solution: Use the workbuffer's configured max luminance (1000, for
example) for the range so that a 200-nit pixel becomes:
(200/1000)^(1/2.2) = 0.48
We also must consistently use the EXT_LINEAR transfer function range in
blurprepare/blurFinish.
Note: KDE somewhat similarly uses gamma 2.2 encoding where 1.0 == max
luminance of monitor:
https://zamundaaa.github.io/wayland/2024/11/02/hdr-and-color-management-in-kwin-part-4.html
paths like enableMirror internalAllocs a new framebuffer in begin()
which means the previously bound currenfFB is reset to 0. if guard it at
end of alloc and restore the previously fb instead of setting it to 0.
there is also codepaths where manually allocated CFLFramebuffers are
created renderbuffers that later called ->bind() that also expects to be
able to read it. bind GL_FRAMEBUFFER in those cases in bind()
and same on release() can be called mid frame on temp buffers deleting
the framebuffer and binding 0 while we still want currentFB bound.
* fix test passing only inconsistently - use acceptsInput to test since `visible` and `hidden` are unreliable
* comment fix
* remove residual sync calls
if previous display manager set a hwcursor and never clears it, we wont
clear it until we actually set a new hw cursor ourself, so add
initialPlaneCleared and clear it once on start. the !CROSSES if case
only clears it if we have actually set it ourself.
if software cursor has been rendered and it now doesnt intersect with
the monitor, clear it out once, guarded by swRendered.
State::monitorState() is destroyed before the renderer during compositor
exit and render pass elements can keep the layersurface alive until the
renderer dies. causing a nullptr deref in ~CLayerSurface() , if guard it
and return early.
* window() already gets the current window
* fix layer invisibility when infullscreening
* format
* smol fix for loop early return
* add current alpha value of layers to `hyprctl layers`
* spacing is hard
* Test - Both default and scrolling
* use .goal() not .value(). also clamp for inf case
* `syncTargetSizeAndPosition()`: use .goal() only as .value() will be overwritten anyway