Hiding the QWindow handle confuses QWidget, which results in user
actions menu not showing up on second launch. Might be a Qt bug.
On the other hand, it makes sense to close dismissed popups, so let's do
it.
This reverts commit 08e392f368.
It appears like with RHI, user code can't mess with its current opengl
context, so let's update shadows immediately.
Just to be sure, shadow cleanup logic in ShadowItem has been hardened to
avoid disturbing the current opengl context unnecessarily.
BUG: 467926
Window::desktop() is obsolete. On the other hand, X11 doesn't support
having a window on several virtual desktops, so we still need it. As a
compromise, this change moves it to X11Window instead.
org.kde.kcm.ConfigModule doesn't exist anymore. Its replacement lives in
org.kde.kcmutils module now.
Note that the replacement has no "quickHelp" property, so it's been
removed. While on this, also drop "ConfigModule.buttons". It still
exists in the new ConfigModule but the default buttons should be fine.
This reverts commit 9cd52b4060.
This commit broke the adjustable scroll speed feature on Wayland. That
feature may not have been implemented in the most technically ideal way,
but simply breaking it and leaving the mouse KCM with UI control that
does nothing isn't great. Besides, there was always a simple way to
avoid any scroll-related regressions caused by this feature: reset the
scroll speed to its default value, which internally is a multiplier of 1
and exercises the same codepath that 9cd52b40 imposes on everyone.
We can come up with a better implementation for Plasma 6.
BUG: 464592
FIXED-IN: 5.27.4
Currently, managed and override-redirect windows are split in two types:
X11Window and Unmanaged. While looking at it strictly from type
perspective, this is great. But it creates other problems, e.g. we need
to put shared X11-specific code in the base Window class or mess with
"base" classes.
As an alternative solution, this change merges the Unmanaged class into
the X11Window class and disables some functionality based on the value
of isUnmanaged().
X11Window::manage() is used to create a managed Window. X11Window::track()
is used to create an unmanaged Window.
As a first step to move away from having an external service remember output settings
for KWin, this commit introduces an output manager that can load configuration files
and generate new output configurations.
It should be irrelevant to the scripts and there's no matching
abstraction on wayland.
is_shape is made protected, but it will be eventually moved to an X11
specific subclass.
Currently, the normal window lifecycle looks as follows: create Window,
wait until it's shown, add it to Workspace, wait until it's closed,
create a Deleted, copy properties from the original window to the
deleted one, destroy the original window, wait until the last deleted
window reference is dropped.
There are a couple of issues with this design: we can't nicely
encapsulate X11 or Wayland specific implementation details if they need
to be accessed for closed windows; manual copying of properties is
cumbersome and error prone and we've had a dozen of cases where effects
worked incorrectly because some properties had not been copied.
The goal of this patch is to drop Deleted and extend the lifetime of the
original window, but with a special state set: Window::isDeleted().
The main danger is that somebody can try to do something with deleted
windows that they should not do, but on the other hand, such code needs
to be guarded with relevant checks too.
When closing a window, we may need to change parent-child relationship
between windows, but we need to preserve stacking order constraints so
dialogs are placed above their parents when they're closed.
This is needed to ensure that Window::isScreenLocker() returns a good
value for closed windows. Also, it's needed to get rid of
ClientConnection::aboutToBeDestroyed() connection, which can cause
problems with window teardown.
If a transient parent is removed, X11Window::removeTransient() will try
to upgrade the transient to a group transient.
On the other hand, that code is broken because Window::removeTransient()
will unset transientFor() so we never hit the code path in the if
statement.
While we could fix it, I think it's not worth it because transient
handling code is already mental and making group transients and normal
transients disjoint will help to keep the things simpler.
Apparently CMAKE_AUTOMOC_MACRO_NAMES modifications are not visible in
sibling directories. To work around that, populate
CMAKE_AUTOMOC_MACRO_NAMES with libkwineffects plugin macros in the
top level CMakeLists.txt file.
QtConcurrent::run()'s return type is marked with [[nodiscard]], which is
not nice to code that just needs to move some tasks to a worker thread.
On the other hand, QThreadPool satisfies our needs too and Qt doesn't
need to construct futures that we won't use.
One remark about the screenshot plugin: the task lambda is mutable so it
cannot be represented using a std::function.
Workspace::outputAt() casts vectors to four rectangle corners and uses
the shortest one to decide which output is the closest to the given
point.
This works poorly on dual monitor setups where on the left side you have
a monitor with landscape orientation and one with portrait orientation
on the right hand side. In that case, outputAt() will prefer the left
monitor even though the right monitor is the closest one if you cast a
perpendicular from the given point to the right monitor.
In order to improve the handling of that case, this change makes
Workspace::outputAt() compute the closest point to the output geometry
rectangle and use the squared distance as the score.
The indirection contributes unnecessary complexity. The usage of
std::weak_ptr and std::shared_ptr complicates the things further, e.g.
![Screenshot_20230325_170226](/uploads/d8b68a9eff47c93c4463bb230b5bbe49/Screenshot_20230325_170226.png)
---
Ideally, same should be done with TabBox and TabBoxHandler, but that can be done in another MR.
"label" is already used.
Warning: The name 'label' (QLabel) is already in use, defaulting to 'label1'.
Warning: The name 'label' (QLabel) is already in use, defaulting to 'label2'.
Deleted windows are no longer destroyed using deleteLater(). They will
be destroyed immediately as Workspace goes through the window list
because the effects will be unloaded by that time.
Tabbox supports two operation modes: switching between windows and
desktops. Switching between windows is more commonly used. Desktop
switching is not exposed in user settings and it requires some advanced
knowledge of kwin's internals to enable it.
On the other hand, over the past years, we've double downed on effects
like desktop grid and overview to provide graphical means to switch
between virtual desktops.
This change drops desktop switching because it's effectively unused to
simplify the tabbox code, which can be very handy for the future
refactorings of window switching.
The `kwin_rules_dialog` executable was used to launch the rules
KCM on a specific window when called from the window menu
because we couldn't depend on the `kde-cli-tools` repo
Since now `kcmshell6` lives on KCMUtils we can call it directly
The property `flat: true`was set since the QML redesign and remained
unnoticed because it didn't actually work.
Now that the qqc2-desktop style has been fixed and correctly draws
flat (non-bordered) comboboxes let's remove it for a nicer look
(just the same as the have had all this time)
Currently, X11Window and Unmanaged call finishCompositing(), which tries
to destroy the window item and other associated compositing data.
Usually, it has no any effect on the window item and the effect window
because they are moved to the Deleted. However, it has some effect on
the XDamage handle.
If the X11 window is unmapped, it will destroy the XDamage handle. If
the X11 window is destroyed, it will do nothing. Why does it behave like
that? Because that's how the XDamage spec is written.
This change removes the call to finishCompositing() and refactors how
the XDamage is handled so Window::finishCompositing() is more generic.
If the X11 window is destroyed, SurfaceItemX11::forgetDamage() will be
called and SurfaceItemX11::~SurfaceItemX11() won't attempt to destroy
the damage handle.
If the X11 window is unmapped, SurfaceItemX11::destroyDamage() will be
called and destroyDamage() in SurfaceItemX11::~SurfaceItemX11() will
noop.
If compositing has been restarted, destroyDamage() in
SurfaceItemX11::~SurfaceItemX11() will destroy the damage handle.
Destroying a zwp_text_input_v3 object should be viewed as disabling it.
isEnabled property is cached because it cannot be computed in
_destroy_resource() handler. By that time, the resource no longer will
be in resourceMap(), so TextInputV3InterfacePrivate::isEnabled() will
erroneously return false even though we expect true.
Currently, input method relies on the fact that QObject::destroyed and
Window::closed are equivalent. But it's going to change, so make the
input method use a signal that's semantically better.
When a window is closed, a Deleted object will be constructed and the
Window's properties will be copied over to it. The long term plan is to
stop doing that, i.e. keep the Window alive but just flip a few flags to
indicate that it's been closed.
In order to unify decoration management, this change ensures that it's
okay to have decorations live as long as the Deleted.
It's needed to work around the cleanup logic of decorations.
Currently, decorations have a valid QObject parent and they're managed
using std::shared_ptr. That's not a perfect combination, but changing it
is also going to be an involved task because the QObject parent is used
to look up the Window.
In long term, it won't matter since we want to get rid of Deleted.
For what it's worth, it restores the order in which Deleted and normal
windows used to be destroyed prior to
995d509e45.
If a client owns several windows (for example it can be the case with
plasmashell) and it crashes, it's possible to encounter the following
case:
- xdg_wm_base resources are destroyed
- xdg_toplevel is destroyed
- another xdg_toplevel is destroyed
When kwin processes the destruction of the first xdg_toplevel, it may
ping the second xdg_toplevel. But the xdg_wm_base is already free()d by
that time, so kwin can access already released memory.
In order to prevent that, make the associated XdgSurfaceInterface
objects inert. Since XdgToplevelInterface and XdgPopupInterface will
become useless after destroying XdgSurfaceInterface, make them inert too.
As the spec states, it's illegal to destroy a bound xdg_wm_base object
while there are still alive xdg surfaces created by it so destroying the
surface role objects should be fine.
This can be useful for the screenshot capture tool if it needs some
information about the captured window or screen, for example to generate
the file name.
Aurorae decorations and several effects are powered by QQuickWindows
that render into offscreen surfaces.
Iterating through all windows and then calling winId() will create a
platform window including for our Aurorae decorations.
Not only is this wasteful but it caused an issue with resizing windows.
QWindow code updates the internal state directly if there's no
underlying platform window, if there is it delegates responsiblity to
the backend. Our own QPA didn't update geometry whilst hidden.
The result of that is Aurorae decorations "randomly" stop resizing
correctly as the contentItem stops resizing to the window size.
BUG: 465790
This makes effect specific cmake code more encapsulated. It's also more
readable if the translation domain is specified explicitly rather than
having it implicitly set by add_definitions().
Window::isShown only checks that it's not hidden, in this case it's not
that it's hidden it's that it's neither shown or hidden. Take the
readyForPainting attribute into account.
Currently it makes an assumption that the name of a scripted effect
starts with "kwin4_effect_" prefix, which has its issues. For example,
it will stop working if we choose to use simpler naming scheme.
This change reworks how the generic scripting kcmodule is constructed.
Instead of guessing kpackage type, make relevant kcms pass it explicitly
via the arg list.
There's other code that includes headers starting from src/ directory,
so putting the corresponding include_directory() in src/effects/ is
inappropriate.
KPluginMetaData::KPluginMetaData(QString) assumes that the file
specified in the string corresponds to a binary plugin now, not a
metadata file.
This fixes scripted effect kcms not working.
Wayland has a limited size for strings in arguments. We should truncate
any strings that come from user-defined data before sending.
We keep the full title around within kwin as it keeps logic simpler.
Size length logic is lifted from QWaylandWindow's setTitle
BUG: 465775
The normal stacking order contains managed and unmanaged windows now.
This kind of breaks dragging from X11 to Wayland clients.
When an X11 client is the drag source, it's going to create an override
redirect window for the drag icon, which is beneath the pointer.
findManagedToplevel() will return the drag icon instead of the window
beneath the drag icon.
The root problem is that normal event processing has different needs. It
doesn't care about window type except when the screen is locked, while
dnd does. Perhaps it also makes sense to check whether the window accepts
focus.
This change introduces a specialized helper to pick the drag target.
Unfortunately, it amounts to some code duplication. On the other hand,
not sure that other options (such as adding flags to findToplevel()) are
better.
Currently windows are scattered in a few separate lists. If you need to
go through the windows, you have to do it piece by piece. On the other
hand, with the overhaul of window types, we've started converging
towards one universal type: Window. Keeping windows in the separate
buckets goes against this design.
Workspace::stackingOrder() already contains all windows. This change
repurposes Workspace::allClientList() from a list of "normal" windows to
all windows, i.e. Workspace::windows(), to be consistent.
There's one API change though. Scripting API will expose other window
types too. This is an intentional change so scripted effects could
operate with all windows. It also matches the current behavior observed
in libkwineffects, which exposes all windows as well.
Instead of having every DrmProperty store pending values, store the data
for the next commit in a separate and temporary type. This simplifies the
code and makes it possible to do commits in a separate thread
Using DMABufs only will not allow clients to fallback to MemFD buffers
in case they fail to import DMABufs for whatever reason and completely
break screen sharing in such case.
Ultimately the best solution would be to implement
https://bugs.kde.org/show_bug.cgi?id=462722, but that hasn't been done
yet, so for now let's use the existing approach of adding the names of
effects into the keywords list for this KCM to surface those effects at
the system level so e.g. people can find them with KRunner.
BUG: 467279
FIXED-IN: 6.0
Even though zwp_text_input_v2_content_hint and
QtWaylandServer::zwp_text_input_v2::content_hint represent the same
values, they are not the same from the compiler perspective.
QVector::count()'s return type is qsizetype. On a 64 bit platform, it's
equivalent to qint64, so "%d" does not suffice.
There are two ways to fix it: use PRIdQSIZETYPE or switch to the stream
operator. Since the warning format is not complex, this takes the latter
approach.
The order in which windows are painted is computed dynamically every
frame. On the other hand, with the introduction of items, it's desired
to avoid doing that so repaints can be scheduled as needed. The
unification also opens the possibilities for more rendering related
refactors to make the code nicer and more reusable.
This makes the behavior of the virtual backend more consistent with
wayland, x11, and drm backends. However, the main advantage is that it's
more nicer to memfd fallback code path in screencasting plugin.
Currently Deleted are destroyed with a delay to avoid dangling pointers
within the middle of painting.
On the other hand, it's reasonable to require not to delete windows when
kwin starts painting the screen.
Over the years, we refactored how deleted windows. They are always
unreferenced after finishing the current frame. So it should be fine to
destroy Deleted immediately now.
The differences between windowed and host flavors of the X11 backend
have become too big, so let's split EglOnXBackend to avoid abstracting
something that makes little sense.
It helps to express the ownership of the pipe fd in ScreenShotSinkPipe2
better.
ScreenShotSinkPipe2 is not made to take a FileDescriptor too because
it's complicated by CaptureInteractive().
kwineffects.h is included in many files and not everyone needs the
RenderTarget and RenderViewport, so forward declare them to reduce the
amount of parsing work for the compiler.
At the moment, the buffers for wsi are allocated implicitly by the EGL
implementation, which is fine for "normal" use cases. But we start
hitting the ceiling the moment we need to something more advanced. For
example the EGL backend creates a dummy fbo object wrapping the default
framebuffer, meaning that we cannot pass it to qtquick (because it can
use its own opengl context).
Another reason for using explicit buffers is that it lets us to clean up
some output related abstractions.
The only purpose ScreenPaintData had was to pass around a copy of the viewport
projection matrix and the effectscreen, which can be handled in a simpler
way separately.
Instead of calling effects->renderTargetRect() and effects->renderTargetScale(),
pass the actually used render target and viewport in all the necessary methods.
This ensures that if an effect renders a screen with a modified scale or
projection matrix, the modified values get used instead of the "global" ones
Qt would need to allocate fewer "tainted" data objects, and using the
same engine both in effects and in kwin is vital for features such as
QML based effects.
When checking for overlap with other windows when placing a new window and cascading to avoid complete overlap, ignore those windows that are already covered by other windows further on the top anyway.
The computation of the covered area is not entirely accurate as it uses the bounding rect rather than the combined rects of the windows, but okay enough for our use case imo.
BUG: 466135
These shortcuts currently don't use the Meta key, which allows them to
block app shortcuts (for example, in the Reaper DAW app). In general
it's a good idea for global shortcuts to use the Meta key to avoid
these kinds of conflicts since apps typically don't use the Meta key
for their own shortcuts. Other axis shortcuts set by KWin components
already do this, so let's do the same thing here.
BUG: 466915
FIXED-IN: 6.0
While the documentation is not clear, it seems that preedit_cursor is
always required for every preedit_string event. Send preedit_cursor for
the preedit_string event we generate upon commit_string.
Scene used to use the clip region as is even if the window is
transformed. That's no longer the case, so stop mutating the clip region
in favor of a more declarative approach to handling window painting.
In order to work around hardware and drivers that aren't capable of applying
a LUT, calculate a per-channel factor for brightness and color temperature
modification. While this ignores color calibration, this makes night color
work until a proper shader based color pipeline is implemented.
BUG: 455720
The ShortcutHandler type provides scripts QML idiomatic way to register
global shortcuts.
There's one caveat about this API though. Since KGlobalAccel does not
allow to change the shortcut by repeating KGlobalAccel::setShortcut(),
the ShortcutHandler requires the default shortcut to be set before it's
constructed.
QFutureInterface is technically internal Qt API and the screenshot uses
it solely because we knew that there won't be any future Qt 5 releases
and it won't be removed in 5.15 patch releases.
In Qt 6, we have proper public API. Unlike QFutureInterface, QPromise is
not copyable, therefore this change also ports some parts of the screenshot
effect from QVector, which uses copy-on-write, to std::vector.
This change removes the window argument to make window signals more
consistent. If you need the window, either use QObject::sender() or
capture it using a lambda.
The outputs already present upon workspace setup wouldn't signal. This
was easily triggered running a standalone kwin session on a tty, it
would manifest with the touchscreen not working complaining that it
didn't have an output assigned yet.
BUG: 466721