Commit graph

515 commits

Author SHA1 Message Date
Martin Gräßlin
a1990e9cc5 [server] Fix regression in SeatInterface::end/cancelPointerPinchGesture
Regression with c72510c932 which removed a
needed source code line.

Thanks build.kde.org!
2016-11-24 09:36:18 +01:00
Martin Gräßlin
b44a8fb556 Implementation of PointerConstraints protcol
Summary:
The pointer constraints protocol is an unstable protocol and thus
the implementation follows the semantics of unstable protocols.

The protocol allows to create a constraint on the pointer - either a
lock or a confinement on a surface. Those are not activated at once, but
when the compositor actively grants it.

During lock no further pointer motion is emitted, during confinement the
pointer is kept in a certain area.

This implements T4451.

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D3466
2016-11-24 09:19:36 +01:00
Martin Gräßlin
c72510c932 [server] Reduce overhead of pointersForSurface
Summary:
In SeatInterface we need to get all PointerInterfaces related to a given
Surface (Client) and call a method on it. The implementation we had so
far went through all Pointers and put all PointerInterfaces into a new
temporary QVector. In most cases all we did then was iterating over the
returned vector.

Which means we created a temporary vector for nothing.

This change implements a kind of std::for_each with the constraints of
the previously used pointersForSurface which does the check that Surface
is not null and that the client matches. If a PointerInterface is found
for that, the passed in method is invoked on it.

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D3295
2016-11-24 09:19:12 +01:00
David Edmundson
8b3ecf8436 Return SurfaceInterface::size in global compositor space
REVIEW: 129358
2016-11-16 14:50:50 +00:00
Martin Gräßlin
bfbc8b9c54 [tools/generator] Generate enum FooInterfaceVersion on server side
With this change the generator is able to detect whether an interface
follows the unstable semantics. In that case the header file on server
side looks different. An enum needs to be generated containing the
interface version. Each of the generated classes has a new method
interfaceVersion returning that enum. The ctor of the class is protected
instead of private.

So far only the header side is adjusted. The implementation currently
generates not matching code.
2016-11-10 08:25:45 +01:00
Martin Gräßlin
40ae294abd [tools/generate] Wrap wl_fixed request args in wl_fixed_from_double
We pass a qreal to the wl_fixed and for that need to wrap it in
wl_fixed_from_double.
2016-11-08 12:29:32 +01:00
Martin Gräßlin
ccdcb43680 [tools/generate] Generate implementation of client side requests
Like in the factored method case, just for generic requests.
2016-11-08 10:58:45 +01:00
Martin Gräßlin
8cbf16b737 [tools/generator] Generate client side resource factories
The code needed in a client global to create a client resource is pretty
much the same in all interfaces. Thus we can generate it.
2016-11-08 10:17:43 +01:00
Martin Gräßlin
64f0117b43 [tools/generator] Generate callbacks and listener on client side
* static void fooCallback definitions added to Private class
* static const foo_listener s_lister added to Private class
* Private::setup generates the foo_add_listner call
* implementation of s_listener added
* base implementation with a TODO marker added for the callbacks
2016-11-08 09:45:28 +01:00
Martin Gräßlin
1bc3818e54 [tools/generator] Pass this as q pointer to Client::Resource::Private
Experience showed that in most cases we need the q pointer in the
resource private class on the client side.
2016-11-08 08:25:33 +01:00
Martin Gräßlin
dba0d77318 [tools/generator] Generate Private::setup(wl_foo *arg) on client side
Experience showed that most generated classes need a dedicated setup
method in the Private in order to add a listener.
2016-11-08 08:00:40 +01:00
Martin Gräßlin
58a6740e48 Fix build - KWayland_SOURCE_DIR instead of KWAYLAND_SOURCE_DIR
Change was prepared prior to project name change. Sorry about breaking.
2016-11-07 13:34:08 +01:00
Martin Gräßlin
a3a7356995 Implementation of PointerGestures protocol
Summary:
Pointer gestures are created for a pointer and there are two types of
gestures: swipe and pinch.

At a given time there can only be one active gesture. The implementation
in SeatInterface ensures that there can only be one active gesture.

Each gesture consists of a start event, 0 to multiple update events and
an end event. The end can also be a cancel. To better support this the
implementation doesn't follow the protocol and splits end and cancel
into dedicated methods in the server side and into dedicated signals in
the client side.

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D3169
2016-11-07 13:28:44 +01:00
Friedrich W. H. Kossebau
4513dad684 Unbreak build: adapt cmake var names to KWAYLAND->KWayland change
project() sets more variables than I remembered

Fix-up for f90f647227508943ec8f919285fd16f0440261b9
2016-11-03 16:46:37 +01:00
Harald Sitter
99bcb89c3b Remove /KF5 include directory injection
This is ancient code that is outright wrong most of the time and at best
just incredibly unnecessary.
It is also not present in the great majority of frameworks due to this.

Its wrongness comes from the fact that it hardcodes the installation path,
which breaks relocatability of the KF5 tree as it will always attempt to
find the include dir $PREFIX/KF5 (e.g. /usr/include/KF5), which may or may
not exist given that the tree was relocated.
Worse yet, in a cross-building scenario we maybe for example
build on ARM and install to /usr but for cross building take the entire ARM
tree and shift it into /arm/usr/. If we then crossbuild on that tree the
bogus include list in this framework will make sure that we always search
in /usr/include/KF5 and thus potentially load a !ARM header simply because
the relevant ARM header was not installed etc.. Similarly of course a
build in $HOME can pick up /usr/include/KF5 headers because the home ones
are missing, causing unexpected results.
This happens whenever the KDE_INSTALL_INCLUDEDIR_KF5 var is absolute, which
it usually is.

On top of all that the premise of the code in question is flawed. It seeks
to add $PREFIX/$KF5INCLUDES to the search paths (e.g. /usr/include/KF5).
This is unnecessary because the target itself is properly installed via
cmake's install(TARGETS ... EXPORT ...) function [1]. This function has
smart functionality built in which will add the passed INCLUDES destination
to the INTERFACE_INCLUDE_DIRECTORIES property of the targets (i.e. what
the useless code wants to do) [2].
So what happens is that we install the target to the
KF5 locations, which has "include/KF5" as INCLUDES location,
thus causing the correct path to be added to the includes list of the
Targets.cmake file.
In particular thanks to more internal magic in cmake it will do so with
automatically resolved root paths such that the installed tree is
relocatable and able to relatively find the other KF5/* headers. So it
does what the code in question wants to do, just correctly.

Since cmake automatically takes care of injecting $prefix/include/KF5 we
can simply get rid of the wrong custom inejection code. This makes the
generated cmake file find the correct include/KF5/ directory and stops it
from always expecting a /usr/include/KF5/ directory to be present.

[1] https://cmake.org/cmake/help/v3.0/command/install.html
[2] https://cmake.org/cmake/help/v3.0/command/install.html
> The INCLUDES DESTINATION specifies a list of directories which will be
> added to the INTERFACE_INCLUDE_DIRECTORIES target property of the
> <targets> when exported by the install(EXPORT) command.

REVIEW: 129273
CHANGELOG: Improved relocatability of CMake export
2016-10-28 14:08:44 +02:00
Martin Gräßlin
de59c3d9b2 [autotests] Fix TestWaylandConnectionThread::testConnectFdNoSocketName
Same as 611df30ecc for the next test
method.
2016-10-28 09:15:24 +02:00
Martin Gräßlin
611df30ecc [autotest] fix WaylandConnectionThread::testConnectFd
The test destroyed the connection prior to destroying registry and event
queue. Thus causing problems. Hopefully this change fixes the segfault
on build.kde.org.
2016-10-28 08:57:22 +02:00
Martin Gräßlin
3f0c879713 [autotests] Try fixing TestWaylandOutputManagement
The test has KWayland::Client objects like Registry as member variables
of the test object. This causes the objects to be destroyed with the
dtor after cleanupTestCase is run which destroys the connection and
Wayland server. At least on the CI system this seems to cause problem.

In general our tests do not keep any state around, especially not
KWayland::Client objects. The normal way is to have a new dedicated
client connection for every test method. This test doesn't follow this
approach at all.

In case that this change does not fix the test and still crashes on
build.kde.org the only option is to drop the test and replace it by a
new variant which follows the approach of other tests.
2016-10-28 08:39:28 +02:00
Martin Gräßlin
37d17b2929 [autotests] Improve TestWaylandOutputManagement::cleanupTestCase
Reorder the cleanup code. It doesn't make sense to delete the client
side objects after deleting the server side objects. This might be a
reason for the failing tests on build.kde.org.
2016-10-28 07:39:15 +02:00
Martin Gräßlin
945b5f086f [tools] Fix generation of wayland_pointer_p.h
It was missing the _p suffix.
2016-10-26 08:44:42 +02:00
Martin Gräßlin
971694c28f [tools] Generate eventQueue methods only for global classes
The event queue gets set by the factory method for resource classes.
2016-10-25 14:29:19 +02:00
Martin Gräßlin
568ab11239 [tools] Generate #include "wayland_pointer.h"
In the client cpp file this include should be generated.
2016-10-25 14:28:39 +02:00
Martin Gräßlin
80d45c4c21 [server] Fix crash on updating focused keyboard surface
Summary:
In case the current selection does not have a DataSourceInterface
updating the focused keyboard surface resulted in a crash. The current
selection is sent to the DataDeviceInterface of the newly focused
client and thus a DataOfferInterface would be created for a null
DataSourceInterface.

This is a similar fix as D3148 and D3149.

Test Plan: Test case added which used to crash before

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D3150
2016-10-24 11:20:13 +02:00
Martin Gräßlin
be04b54827 [server] Fix possible crash on creation of DataDevice
Summary:
This is a similar condition as D3148. If a DataDeviceInterface is
created for the currently focused keyboard Surface the current selection
is sent to the new DataDeviceInterface. If the current selection does
not have a DataSourceInterface a DataOfferInterface for a null
DataSourceInterface would be created and result in a crash.

This change verifies that there is a DataSourcInterface on the current
selection prior to sending out the selection.

Test Plan:
A test case is added which simulates the condition by
using two clients.

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D3149
2016-10-24 11:08:07 +02:00
Martin Gräßlin
988a239637 [server] Ensure we have a DataSource on the DataDevice in setSelection
Summary:
SeatInterface provides a way to set the current selection. This method
did not verify whether the new DataDeviceInterface actually has a
DataSourceInterface. If there is no DataSourceInterface on that
DataDeviceInterface the selection should not be sent to the current
selection owner. This results in a crash as DataOfferInterface
(correctly) doesn't expect the passed in DataSourceInterface to be null.

To ensure we don't hit this again the DataOfferInterface ctor gained an
Q_ASSERT to validate the DataSourceInterface.

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D3148
2016-10-24 10:08:59 +02:00
Martin Gräßlin
a037a0cb4f [tools/generator] Improve resource destruction on server side
The generator misdetected the destructor Requests by looking at the
arguments instead of the type of the request.

In addition the destructor handling changed in KWayland::Server since
the generator got created. There is now a shared implementation for the
Resource destruction. The generator is adjusted to generate the code for
that and implements the destruction for the Global resource destruction.
2016-10-20 14:53:43 +02:00
Martin Gräßlin
41d07de410 Add request to have focus in a PlasmaShellSurface of Role Panel
Summary:
By default a panel does not take focus. But there are panels which
should get keyboard focus. Examples in a Plasma session are the widget
explorer.

This change adds a new request to PlasmaShell interface to specify
whether a panel should get focus. The compositor can use this request to
decide whether to pass focus to a panel.

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D3035
2016-10-18 07:47:10 +02:00
Martin Gräßlin
c291752819 Add auto-hiding panel support to PlasmaShellSurface interface
Summary:
This change adds support for auto-hiding panels. A PlasmaShellSurface
with Role Panel and PanelBehavior AutoHide can request to get
auto-hidden at a screen edge. The compositor will then not show the
surface although it is still mapped and will show it again once the
screen edge gets triggered.

The interface is extended by one new request to allow the client to
request the hiding of the surface. In addition two events are added to
inform the client when the surface got hidden and when it got shown
again.

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D3007
2016-10-17 09:04:16 +02:00
Martin Gräßlin
721ebe1875 Fix build (try 1)
Sorry, it compiled on my system. Trying to fix.
2016-10-17 07:45:35 +02:00
Martin Gräßlin
d92592a291 Support passing generic QIcon through PlasmaWindow interface
Summary:
Especially for Xwayland windows the compositor might not have a themed
icon name. Resulting in a task manager not having dedicated icons for
Xwayland windows.

This change deprecates the way how a compositor is supposed to set the
window icon. Instead of passing the themed icon name, it is now supposed to
pass the QIcon. In case it's a themed icon the existing way to pass to
the client is used.

Otherwise a new event is used to inform the client that there is an icon
- no data is transmitted at this point. The client can then create a
file descriptor and pass it to the compositor. The compositor serializes
the icon into the file descriptor and the client can read from it. This
all happens transparently on client side there is no api change at all.

The writing and reading of the icon is done in a thread. Due to that
Qt5::Concurrent is now a required dependency instead of an optional
dependency.

Reviewers: #plasma_on_wayland, hein

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D3049
2016-10-17 07:35:21 +02:00
Martin Gräßlin
bd34a6d828 [server] Implement the generic window property in QtSurfaceExtension
Summary:
Qt supports setting generic data on a QWindow. This change implements
the callback properly and forwards the property to the surface extension
instance. This allows the compositor to e.g. listen to
DynamicPropertyChangeEvents and get access to all additional set
properties.

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D3045
2016-10-17 07:34:12 +02:00
Martin Gräßlin
336ff134da [client] Add methods to get ShellSurface from a QWindow
Summary:
This is similar to what already exists for Surface. With this methods
it's possible to get a ShellSurface from an existing QWindow and to
perform low level native calls directly for the ShellSurface.

Similar calls will also be needed for XdgShellSurface, though the
xdg_shell_surface is not yet available through the native interface.

Test Plan: Used in breeze to trigger window moving

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D3018
2016-10-17 07:33:06 +02:00
Martin Gräßlin
97afd2658d [server] Send pointer events to all wl_pointer resources of a client
Summary:
This is what Weston does. With this change clients can create
multiple wl_pointer instances and thus get events reported to all of them.
This will be needed to e.g. support drag on empty area in Breeze on Wayland.

A similar change was done for wl_keyboard already in 25dbc84d.

Test Plan: Seat auto test still passes

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D3016
2016-10-17 07:32:12 +02:00
Martin Gräßlin
9e5177cb36 [server] Don't call wl_data_source_send_send if DataSource is unbound
This could result in a crash as the added test case shows.

Reviewed-By: bshah
2016-10-12 08:08:28 +02:00
Martin Gräßlin
39fc8a4b4f Fix heap-use-after-free in TestWaylandSeat::testDisconnect 2016-10-11 08:37:55 +02:00
Martin Gräßlin
2b8900daf5 Fix heap-use-after-free in TestWaylandShell::testClientDisconnecting 2016-10-11 08:34:27 +02:00
Martin Gräßlin
bbbfb48f48 Fix build
Add missing include of QVector. Sorry built on my system without it.
2016-10-11 08:05:15 +02:00
Martin Gräßlin
0649c8e51e [server] Use deleteLater when a ClientConnection gets destroyed
Summary:
In the situation that a wl_client gets destroyed while still
wl_resources are around it can happen that one of them calls into the
ClientConnection during the cleanup handling which gets triggered at the
same time. This can then trigger a crash.

This change uses deleteLater for the ClientConnection and sets the hold
wl_client pointer to null instead of deleting directly. So the
ClientConnection is still around while the Resources gets cleaned up.
This is similar to the cleanup of Resource where on unbind the
wl_resource pointer is set to null and the Resource gets delete later.

BUG: 370232
FIXED-IN: 5.28

Reviewers: #plasma, bshah

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D3004
2016-10-11 07:41:17 +02:00
Martin Gräßlin
a96776ac0e Implement support for the relative pointer protocol
Summary:
This change implements the zwp_relative_pointer_v1 protocol which allows
to send relative motion events.

The (unstable) protocol consists of a RelativePointerManager which
creates RelativePointers for a given Pointer. This interface currently
only has one event to report the relative motion. It carries the delta,
the non-accelerated-delta and a timestamp in microsends granularity.

On the server side the implementation is mostly internal. Once a
RelativePointerManagerInterface is created one can send relative motion
events through the SeatInterface. The SeatInterface takes care of
sending it to the responding RelativePointerInterface. The protocol does
not restrict the sending of "normal" and relative motion events. Thus it
can be combined in any way one wants. This allows to have a rather
simple implementation. A user of the SeatInterface can just start to
feed the relative motion events (if the information is available) to the
SeatInterface together with the pointer events.

On client side a new RelativePointerManager and RelativePointer class
are added. The RelativePointerManager creates the RelativePointer for a
given Pointer. The event sent to RelativePointer is transformed in a
normal signal.

Reviewers: #plasma

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D2978
2016-10-11 07:40:54 +02:00
Martin Gräßlin
9f3d6c8f84 [server] Cancel previous selection from SeatInterface::setSelection
Summary:
When changing the selection the previous selection needs to be
cancelled. This is already done in the "normal" updating of the
selection. If the previous selection doesn't get cancelled QtWayland is
not able to accept anything new from the clipboard. The setSelection
didn't cancel it yet, due to that copy from Xwayland to QtWayland
windows doesn't work in KWin as KWin uses the setSelection call for the
Xwayland clipboard.

With this change the cancelling of previous selection is moved into a
dedicated method and called from the normal way and the setSelection
way.

Reviewers: #plasma_on_wayland, bshah

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D2997
2016-10-10 10:54:44 +02:00
Martin Gräßlin
25dbc84dbc [server] Send key events to all wl_keyboard resources of a client
Summary:
This is what Weston does. With this change clients can create multiple
wl_keyboard instances and thus get events reported to all of them. This
will be needed to e.g. support KModifierKeyInfo on Wayland.

Similar changes are probably also needed for pointer and touch.

Test Plan:
Auto test for seat still passes. A custom change to kscreenlocker
is able to report whether caps lock is on with this change.

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D2963
2016-10-06 14:50:23 +02:00
Martin Gräßlin
9e8f123513 [server] Don't send key release for not pressed keys and no double key press
Summary:
This change makes use of the internal key state in better way. If a
key is not considered pressed, no key release is sent. This can happen
for example if the compositor grabs a key press (global shortcut) but not
the release. The Wayland client cannot do anything with the release as it
never got the press. Thus it doesn't make sense to send the release.

Similar if a key is already pressed, it doesn't make sense to send
another press event. This ensures that if the server sends in repeating
key presses they are filtered out. Key repeat is handled on client side.
Also if several physical keys send the same key code, pressing them at
the same time won't send double press/release event.

This change might cause regressions in KWin in case KWin does not handle
the situation correctly. But that would be a bug in KWin which needs to
be fixed there. If it causes regressions the bug might have shown in
other situations as well.

BUG: 366625
FIXED-IN: 5.27

Reviewers: #plasma_on_wayland, #kwin

Subscribers: plasma-devel, kwin

Tags: #plasma_on_wayland, #kwin

Differential Revision: https://phabricator.kde.org/D2786
2016-09-15 09:35:13 +02:00
Martin Gräßlin
2f1beca4bf [server] When replacing the clipboard selection previous DataSource needs to be cancelled
Summary:
According to the Wayland documentation a data source needs to be
cancelled whenever it is no longer valid. A reason for no longer being
valid is that the data source has been replaced by another data source.

So far KWayland did not implement this aspect which resulted in clipboard
breaking in QtWayland applications. As soon as one copied once from an
application it was no longer possible to paste to it from another
application.

With this change the data source gets properly cancelled and also
ensured that the server code doesn't run into a possible crash condition
when trying to cancel an already unbound data source.

BUG: 368391

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D2743
2016-09-14 10:22:38 +02:00
Martin Gräßlin
cd29376ad7 Try to fix build: add missing includes
Sorry about that, it compiled on my system.
2016-09-13 08:46:39 +02:00
Martin Gräßlin
9f92a05f52 Add support for Surface enter/leave events
Summary:
This change implements support for the wl_surface events enter and
leave. Those events are emitted whenever a surface becomes visible on
an output by e.g. mapping the surface, moving or resizing it. Similar
the leave is sent whenever the surface is no longer on an output.

The server side is not yet fully complete yet. It also needs to emit
when the client binds the output another time and needs to send a
leave before destroying the output.

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D2528
2016-09-13 08:32:50 +02:00
Martin Gräßlin
2cf09cb50d [client] Track all created Outputs and add static get method
Summary:
This change starts to track all Outputs and introduces a static
method to get an Output* for a wl_output* in case the wl_output* is
known to Output.

This is needed for the enter and leave events on wl_surface.

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D2526
2016-09-13 08:29:04 +02:00
Martin Gräßlin
34eb146db7 [autotests] Try to make TestWindowManagement more robust
The test started to segfault on build.kde.org. It looks like an event
survives the destruction of the server. Thus this change tries to
dispatchEvents once more before destroying everything.
2016-08-22 15:57:25 +02:00
Martin Gräßlin
31a434b633 [autotest] Try making IdleTest more robust
It started to fail on build.kde.org with a segfault. While I cannot
reproduce this locally it looks like client objects survive to the next
test and thus cause issues.

This change attempts to reduce the risk by making sure that everything
is cleaned up correctly. If that fixes the issue we can look into a
proper fix.
2016-08-22 15:32:02 +02:00
Martin Gräßlin
618bebb63b Make linux/input.h compile time optional
Summary:
Instead of hard depending on the include of linux/input.h we check
whether that include file exists and properly ifdef all usages.

Unfortunately there is no replacement for those parts which do mapping
of input event codes.

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D2344
2016-08-22 14:36:11 +02:00
Martin Gräßlin
233e388e02 [autotests] Try making TestWaylandSurface::testDisconnect more robust
On build.kde.org the Surface is often already destroyed when returning
from waiting on client disconnected.

This change tries to handle the situation better: only if the signal
is not yet emitted, try to wait for it.
2016-08-08 08:38:57 +02:00