Item::scheduleRepaint() invalidates part of an item. It doesn't
invalidate the corresponding part of the scene globally. There are a
couple of reasons why it works the way it is:
- the first, and the main one, is to keep effects like blur working
- the second is to cull out invisible repaints, i.e. repaints scheduled
by obscured items
This kind of repaints is suitable when the size or the position of the
item changes. However, it's not good in case the stacking order changes.
For example, consider two sibling items: `[A, B]`, `B` is on top of
`A`. If the `z` of item `B` is set to `-1`, the effective stacking order
will be `[B, A]`, and only repaints for item `B` will be scheduled. When
`WorkspaceScene::preparePaintSimpleScreen()` processes the next frame, it
will see that item B is occluded by item A, so it will discard item B's
repaints and the corresponding graphics buffer will _not_ be repainted
even though it should be.
In order to prevent that, we need to schedule a global repaint.
Is there a less error prone design? Yes, if we could specify the contents
of every frame declaratively, then we could diff two consecutive frames
without manual meticulous repaint tracking. The magnitude of such changes
is beyond a bugfix though.
By default, we want the primary GPU to be one that displays are connected to, and if we're
on a laptop, one that the internal display is connected to.
BUG: 494749
The drm backend needs the renderer to allocate buffers when Workspace tries to enable outputs,
so it needs to get created before Workspace in order for output querying to happen at that point
as well.
The scene still gets created after Workspace.
There cannot be two XSync requests in flight, the type of the sync
requests doesn't matter either, e.g. one for interactive resize or
one to determine whether the client has painted the initial frame.
When the wl_surface commits are blocked by the initial sync request, it
is really important that Xwayland doesn't commit the surface until the
sync request is acked. However, with the current arrangement of the code,
Xwayland may render something before the sync request is acked.
It can happen because the frame window is mapped before the initial sync
request is sent. There are many places where it can happen, e.g. in the
setupCompositing() function, or the setMinimized() function, etc.
In order to ensure that Xwayland won't render the wl_surface while we
are waiting for the sync request to get acked, this change moves the initial
sync request all the way to the top of the manage() function so the
surface commits are blocked before the frame window is mapped.
XSYNC requests and wl_surface commits are unsynchronized. This results
in the window bouncing when it's being resized.
Let's consider a concrete example. Assume that there is a window with 0,0
100x100 geometry and it is being resized by dragging the left edge. If
the left edge is dragged by 10px, the following will occur:
- wl_surface commits will be blocked (it is needed to ensure the
consistent order of XSync acknowledgements and wl_surface commits)
- an XSync request will be sent
- a ConfigureNotify event will be sent
- a client processes the ConfigureNotify by repainting the window and
acknowledges the XSync request
- kwin notices that the XSync request has been acked and updates the
window position to 10,0 and unblocks surface commits
The problem is that it can take a while for Xwayland to attach a new
buffer to the surface with a size of 90x100. If kwin composes a frame in
meanwhile, the effective geometry of the window will be 10,0 100x100,
i.e. the right window edge will stick by 10px. Some time later, Xwayland
would attach a buffer with the right size (90x100), and the right window
edge will be put back in the right place.
In order to address the bouncing, this change reworks how the
synchronization is performed:
- when a window is asked to resize, kwin will freeze wl_surface commits,
send a sync request, and configure the window
- after the client repaints the window, it acks the sync request
- when kwin sees that the sync request has been acked, it will unfreeze
the wl_surface commits. And here's the most important part: it will NOT
update the window position until Xwayland commits something
- when Xwayland commits the wl_surface, kwin will update the window geometry
It's important to wait until Xwayland commits the wl_surface because, as
it was said previously, it can take a while until Xwayland commits the
wl_surface and kwin could compose a frame with the new position but old
surface size in meanwhile.
BUG: 486464
There are two timeouts: a soft one and a hard one. If the soft timeout
occurs, then the scheduled operation will be performed. For example,
the window will be marked as ready for painting or resized. If the hard
timeout occurs, _NET_WM_SYNC_REQUEST will be disabled.
Such an arrangement is fine in its current present form, but in order
to make Xwayland window resizing less glitchy, _NET_WM_SYNC_REQUEST
code needs to interact with wl_surface event flow, which in its turn
means that the timeout code also needs to be prepared for that. It is
very challenging to make the timeout code not break, so this change
seeks to re-arrange the timeout handling so it's easier to integrate
with wl_surface commits.
With the proposed changes, there is going to be only one timer: timeout.
If it fires, the window will be resized immediately and XSync is going
to be kept disabled until an acknowledgement arrives from the client.
The fact that X11Window::handleSyncTimeout() is shared by code that runs
when the client supports or doesn't support _NET_WM_SYNC_REQUEST makes
the XSync code difficult to follow and more error prone.
On the other hand, it appears that other window managers, e.g. Mutter and
openbox, don't bother about throttling interactive resize when the client
doesn't opt in into _NET_WM_SYNC_REQUEST, so let's do the same to simplify
the code.
As a backup plan, if it indeed becomes a problem later, we can always
save current monotonic time in X11Window::doInteractiveResizeSync() and
make X11Window::isWaitingForInteractiveResizeSync() check whether enough
of time has passed since the last resize sync.
Currently, the displayfd file descriptors are leaked. Instead of the
implicit approach, take the approach where we explicitly specify what
file descriptors must be passed to Xwayland.
Note that the start() function is still a bit leaky.
The -wm file descriptor leak prevents the poll() function from returning
POLLHUP when Xwayland dies.
The POLLHUP status will be set when all file descriptors for the other
end point are closed.
BUG: 442846
Edge::activatesForPointer() needs the virtual desktop manager to be
fully initialized. It's also important to know that the
activatesForPointer() function can be called when recreating screen
edges.
During the startup process, the Workspace can update outputs, which
will also trigger screen edge recreation. The problem is that
the Workspace does that before the virtual desktop manager is fully
initialized.
As a potential solution, make the Workspace update outputs a bit later.
This new option
- activates on click
- passes clicks
- raises only on release
This way, if a user starts a drag on a window lower in the stacking order, it does
not get raised above other windows immediately, which makes drag and drop less
annoying to deal with
BUG: 489806
There's no reason to disallow it; while it's not necessarily ideal to use a non-zero
wideness for color critical workflows, that's up to the user to decide.
highlightWindows is an internal effect used to highlight one specific
window whilst hiding all others. It's used by the tabbox and by
plasmashell's task manager when hovering over a thumbnail.
The user may enable or disable usage of this effect for the main and
alternative task switcher. If it is enabled for neither, we currently
disable the entire effect, regardless of whether or not it is still in
use by plasmashell. This is not visible immediately, but will take until
the next reboot or login to become active.
As a dedicated configuration toggle for this internal effect is missing,
the user cannot reasonably enable this feature again. They would have to
know to enable either task switcher to use this effect again and, since
the effect isn't reloaded automatically, reboot or relogin.
Since this is an internal effect, we should simply not allow it to be
disabled globally via either task switcher setting. Both tabbox and
plasmashell already carry their own configuration settings to enable
usage of this effect, so users can still tweak the behaviour there
without also affecting other components.
There are cases where the minimum luminance can be lower than the transfer function's minimum; in those
cases, the transfer function's minimum would get mapped to a value greater than black in the target
transfer function. To avoid that, this just takes the max. of the metadata and transfer function minimum
BUG: 494854
If a window is already being moved, just switch the current virtual
desktop rather than update Workspace::moveResizeWindow() which is going
to trip an assert.
Add a new m_requestedTile member that gets set immediately
with either requestTile() or setQuickTileMode(), at
XdgToplevelWindow::handleStatesAcknowledged()
Window::commitTile() will be called and m_tile will be actually
set only on that step