The .clang-format file is based on the one in ECM except the following
style options:
- AlwaysBreakBeforeMultilineStrings
- BinPackArguments
- BinPackParameters
- ColumnLimit
- BreakBeforeBraces
- KeepEmptyLinesAtTheStartOfBlocks
A good portion of geometry handling code was written during the X11
times. The main difference between X11 and Wayland is that kwin doesn't
know where a window will exactly be after resize() or moveResize().
In order to handle Wayland specifics, every window has a bounding
geometry that is being manipulated by move(), resize(), and moveResize().
The frameGeometry(), the clientGeometry(), and the bufferGeometry() are
not manipulated by move(), resize(), and moveResize() directly. Almost
everything that manipulates geometry should use moveResizeGeometry().
This creates a problem though, since the clientGeometry() will be
updated only after the client provides a new buffer, kwin has absolutely
no idea what the client geometry for a given move resize geometry will
be.
Another side of the coin is that decoration updates are performed
asynchronously on wayland, meaning that you cannot use border properties
for anything related to geometry handling and you should avoid using
borderLeft(), borderTop(), borderRight(), and borderBottom() in general.
clientGeometry(), bufferGeometry(), and border*() are good only if you
want to forward an event or render something. They can't be used for
manipulating the geometry.
Unfortunately, AbstractClient::checkWorkspacePosition() needs both,
which is a bit of a problem. To add more oil to the fire, contents
of a decorated window can be snapped to a screen edge. This goes against
the nature of geometry updates on wayland, where we try to indicate
the bounds of the frame geometry and avoid using client and buffer
geometries.
In order to make geometry handling more correct on wayland, this change
removes the ability to snap the contents of a decorated window to a
screen edge. This allows to avoid using the client geometry in
checkWorkspacePosition(), which is a very important function that ensures
the window is inside the workspace.
There is nothing wrong with snapping the frame rather than its contents
and that's what kwin used to do. It was changed with the removal of
"Display borders on maximized windows" option, the relevant commit
didn't provide any reasoning behind the change.
On Wayland, the move resize geometry and the frame geometry are
completely out of sync.
This change synchronizes emitting of the clientStepUserMovedResized
signal to the move resize geometry changes.
It simplifies code of InternalClient and XdgSurfaceClient, and makes
adding support for other shell surface protocols easier as there's less
boilerplate stuff that you would need to take care of.
With internal clients and xdg-shell clients, geometry updates occur in
asynchronous fashion when interactively resizing the window.
As is, performInteractiveMoveResize() will call resize() if the move
resize geometry is different from the current frame geometry. This can
result in kwin sending excessive configure events.
With this change, kwin will send less configure events during
interactive resize.
They are used only by InternalClient. AbstractClient doesn't need to
handle the destruction of DecorationBridge because its lifetime matches
kwin's lifetime.
This simplifies focus related logic a bit. Instead of differentiating
between wayland and internal window focus, simply maintain window focus
that works both with regular wayland windows as well as the ones created
by kwin.
Currently, AbstractClient::geometryRestore() is abused to put windows
back on their original screen. It makes window placement more complex
and it breaks restoring initially maximized windows.
The main idea behind _NET_WM_FRAME_OVERLAP is to extend the borders of
the server-side decoration so the application can draw on top of it. It
was inspired by similar feature in Windows.
However, _NET_WM_FRAME_OVERLAP is basically unused. Neither GTK nor Qt
support it and I have never seen any application that uses it.
At the moment, kwin is the only compositing window manager that supports
_NET_WM_FRAME_OVERLAP. Neither mutter nor compiz nor compton and so on
support it.
Since _NET_WM_FRAME_OVERLAP is practically unused, there's no point for
keeping supporting it.
This change shouldn't affect any existing app as _NET_WM_FRAME_OVERLAP
atom is not listed in _NET_SUPPORTED.
Window management features were written with synchronous geometry
updates in mind. Currently, this poses a big problem on Wayland because
geometry updates are done in asynchronous fashion there.
At the moment, geometry is updated in a so called pseudo-asynchronous
fashion, meaning that the frame geometry will be reset to the old value
once geometry updates are unblocked. The main drawback of this approach
is that it is too error prone, the data flow is hard to comprehend, etc.
It is worth noting that there is already a machinery to perform async
geometry which is used during interactive move/resize operations.
This change extends the move/resize geometry usage beyond interactive
move/resize to make asynchronous geometry updates less error prone and
easier to comprehend.
With the proposed solution, all geometry updates must be done on the
move/resize geometry first. After that, the new geometry is passed on to
the Client-specific implementation of moveResizeInternal().
To be more specific, the frameGeometry() returns the current frame
geometry, it is primarily useful only to the scene. If you want to move
or resize a window, you need to use moveResizeGeometry() because it
corresponds to the last requested frame geometry.
It is worth noting that the moveResizeGeometry() returns the desired
bounding geometry. The client may commit the xdg_toplevel surface with a
slightly smaller window geometry, for example to enforce a specific
aspect ratio. The client is not allowed to resize beyond the size as
indicated in moveResizeGeometry().
The data flow is very simple: moveResize() updates the move/resize
geometry and calls the client-specific implementation of the
moveResizeInternal() method. Based on whether a configure event is
needed, moveResizeInternal() will update the frameGeometry() either
immediately or after the client commits a new buffer.
Unfortunately, both the compositor and xdg-shell clients try to update
the window geometry. It means that it's possible to have conflicts
between the two. With this change, the compositor's move resize geometry
will be synced only if there are no pending configure events, meaning
that the user doesn't try to resize the window.
The Toplevel::clientContentPos() function is needed to map the surface
local coordinates to the global coordinates. But its name is highly
confusing as there's already a function with a similar name. This change
introduces a helper with a better name to fix the readability issue.
This is to improve code readability and make it easier to differentiate
between methods that are used during interactive move-resize and normal
move-resize methods in the future.
This makes the implementation of the buffer geometry consistent with the
frame geometry and the client geometry and removes a virtual method call
from a few hot paths.
We need to emit the clientFinishUserMovedResized signal to notify
effects such as translucency that the interactive move-resize is
finished. Otherwise, the set() animation won't be cancelled and the
window will get stuck frozen.
BUG: 409376
With the client-side decoration changes, kwin will properly determine
whether the window needs to be configured even if the frame geometry has
not changed.
This change slightly changes the semantics of the setFrameGeometry()
method. Prior to this, it was possible to force a geometry, i.e. block
other geometry updates, however such a behavior is counter-intuitive and
it exponentially increases the complexity of code.
As far as I know, the force flag was needed to propagate geometry
changes if the frame geometry doesn't change, but the client geometry
does. With the client-side decoration changes, the force flag is not
needed, as kwin now takes into account the client geometry and the frame
geometry when determining whether to send a configure event.
Currently, the Workspace has no any api to constrain one window above
another. This results in having hacks such as keepDeletedTransientAbove()
This change introduces a basic api to constrain a given window above
another. It can be used for ensuring that transient windows are placed
above their parents. It also can be used for stacking the outline window
below the move-resize window.
Internal windows may also have transient parents. Because of that, this
change makes the workspace add internal clients to the stacking order by
default. The good thing about it is that it allows us unify some input
related code for "external" windows and internal windows.
SurfaceItemInternal will discard the current pixmap if the buffer size
changes. Also, one of the goal of the scene redesign is to keep things
such as this out of Toplevel subclasses.
Currently, dealing with sub-surfaces is very difficult due to the scene
design being heavily influenced by X11 requirements.
The goal of this change is to re-work scene abstractions to make improving
the wayland support easier.
The Item class is based on the QQuickItem class. My hope is that one day
we will be able to transition to QtQuick for painting scene, but in
meanwhile it makes more sense to have a minimalistic internal item class.
The WindowItem class represents a window. The SurfaceItem class represents
the contents of either an X11, or a Wayland, or an internal surface. The
DecorationItem and the ShadowItem class represent the server-side deco and
drop-shadow, respectively.
At the moment, the SurfaceItem is bound to the scene window, but the long
term plan is to break that connection so we could re-use the SurfaceItem
for things such as software cursors and drag-and-drop additional icons.
One of the responsibilities of the Item is to schedule repaints as needed.
Ideally, there shouldn't be any addRepaint() calls in the core code. The
Item class schedules repaints on geometry updates. In the future, it also
has to request an update if its opacity or visibility changes.
We're now sharing most of the X11Client activity behavior accross all
clients. This allows to cleanup some of the existing virtuals and remove
quite a bit of code overalls.
Has to introduce an extra platform specific hook since X11Client
serializes the activity information in an atom and we will probably need
to do something similar on the Wayland platform at some point.
This allows us to start interacting with the activities with kwin
wayland. They are not restored properly accross sessions though since
nothing is really persisted and the session management still seems to
be amiss.
Once in a while, we receive complaints from other fellow KDE developers
about the file organization of kwin. This change addresses some of those
complaints by moving all of source code in a separate directory, src/,
thus making the project structure more traditional. Things such as tests
are kept in their own toplevel directories.
This change may wreak havoc on merge requests that add new files to kwin,
but if a patch modifies an already existing file, git should be smart
enough to figure out that the file has been relocated.
We may potentially split the src/ directory further to make navigating
the source code easier, but hopefully this is good enough already.