This fixes a porting typo. Previously, the modal was therefore
added twice, once for itself and once for its parent but we actually
do *not* want a window with a modal child at all.
Currently, input devices depend on InputRedirection for the event enums.
Move them to the InputDevice to prevent input backends depending on higher
level abstraction layers.
Tablet tools are independent of tablets but the way our code is
structured is that it assumes they are not. For example, the same tool
can move between two different tablets.
This change introduces the InputDeviceTabletTool type which abstracts
tablet tools. It allows to look up TabletToolV2Interface by just looking
at the tablet tool pointer.
It also opens up "smarter" strategies to clean up stale tool objects.
Previously, there used be issues with unregistration of tablet input
devices, which are resolved now. So, the null checks can be dropped to
make the code easier.
As of now, only libinput tablet input devices are properly registered
with the wp_tablet_v2 protocol. This is not great for testing purposes
and it limits the options how we would structure the code, e.g.
the wp_tablet_v2 implementation can't work with InputDevice even though
it would be nice to offload some things from tablet_input.cpp to it.
If we change the backend the colormap will get leak, the colormap should
be released with xcb_free_colormap before the window destoryed.
Signed-off-by: Chaojiang Luo <luochaojiang@uniontech.com>
Since the position of the contentItem depends on the position and scale
of the parent item, make sure to re-evaluate it when the parent changes.
BUG:495501
This is needed to workaround a test failure in testButtonRebind. The
current issue is that tablet input is built around libinput backend,
but tests create fake input devices to represent tablets, so things such
as TabletV2Interface or TabletPadV2Interface are not registered as
expected.
In order to address the issue, input devices need to expose tablet
specific metadata in some way that doesn't require using libinput specific
apis. This will be done later.
Once the tests are fixed, we should be able to drop tablet null checks
in tabletToolEvent() functions.
Device group user data is a libinput specific concept, and it's not
portable to other platforms/backends, which we need to support in long
term for proper testing of tablet stuff in CI, etc.
Note that tablet input still heavily pokes libinput specific things,
this is going to be addressed later.
Tablet pad and tablet tool input devices can be announced in any order.
The problem with the current code is that it is going to create a
TabletV2Interface object when a tablet pad is registered first. In addition
to that, it unsets the user data (TabletV2Interface) in libinput device
group without checking whether the tablet tool is actually removed.
Another issue is that if a tablet pad is registered first, then the
TabletV2Interface is going to have the metadata of the tablet pad input
device. Tablet pad and tablet tool devices are often represented separately.
BUG: 493027
Maintaining tablet <-> pad one-to-one mapping is not quite accurate.
A tablet can potentially have more than one pad paired with it.
The main motivation behind this change is to decouple tablet pad
registration from tablet tool registration.
The InputDevice is useful for determining the origin of the event.
TabletPadId acts like it, but it still suffers from issues where we
need to access the InputDevice.
Currently, tablet pad event data is provided using function arguments,
but this approach is not good in long term. For example, if more data
needs to be supplied, then every user needs adjustments.
This change introduces more tablet event types to make the code more
flexible in terms of extending event payload.
After 5f85280563, when clicking a window,
it will be raised on button release. While it works as expected for
dnd, for interactive move or resize, it's preferred to raise the window
as soon as it's possible.
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.