2020-08-02 22:22:19 +00:00
|
|
|
/*
|
|
|
|
KWin - the KDE window manager
|
|
|
|
This file is part of the KDE project.
|
2015-03-20 13:41:03 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org>
|
2015-03-20 13:41:03 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
2016-04-07 07:24:17 +00:00
|
|
|
#include "platform.h"
|
2019-08-28 18:54:37 +00:00
|
|
|
|
|
|
|
#include "abstract_output.h"
|
2015-04-02 12:37:23 +00:00
|
|
|
#include <config-kwin.h>
|
2015-04-01 13:36:40 +00:00
|
|
|
#include "composite.h"
|
|
|
|
#include "cursor.h"
|
2017-08-21 06:53:56 +00:00
|
|
|
#include "effects.h"
|
2017-09-21 12:52:46 +00:00
|
|
|
#include <KCoreAddons>
|
2017-08-07 15:54:56 +00:00
|
|
|
#include "overlaywindow.h"
|
2017-08-21 09:59:52 +00:00
|
|
|
#include "outline.h"
|
2016-02-23 11:29:05 +00:00
|
|
|
#include "pointer_input.h"
|
2017-09-08 13:49:52 +00:00
|
|
|
#include "scene.h"
|
2019-08-28 18:54:37 +00:00
|
|
|
#include "screens.h"
|
2016-04-15 11:47:56 +00:00
|
|
|
#include "screenedge.h"
|
2015-03-20 13:41:03 +00:00
|
|
|
#include "wayland_server.h"
|
[colorcorrection] Night Color - blue light filter at nighttime
With Wayland KWin needs to provide certain services, which were provided
before that by the Xserver. One of these is gamma correction, which includes
the - by many people beloved - functionality to reduce the blue light at
nighttime. This patch provides the KWin part of that. It is self contained,
but in the end will work in tandem with a lib in Plasma Workspace and a KCM
in Plasma Desktop, which can be used to configure Night Color.
* Three modi:
** Automatic: The location and sun timings are determined automatically
(location data updates will be provided by the workspace)
** Location: The sun timings are determined by fixed location data
** Timings: The sun timings are set manually by the user
* Color temperature value changes are smoothly applied:
** Configuration changes, which lead to other current values are changed
in a quick way over a few seconds
** Changes on sunrise and sunset are applied slowly over the course of few
minutes till several hours depending on the configuration
* The current color value is set immediately at startup or after suspend
phases and VT switches. There is no flickering.
* All configuration is done via a DBus interface, changed values are tested
on correctness and applied atomically
* Self contained mechanism, speaks directly to the hardware by setting the
gamma ramps on the CRTC
* Currently working on DRM backend, extensible to other platform backends in
the future
* The code is written in a way to make the classes later easily extendable to
also provide normal color correction, as it's currently done by KGamma on X
Test Plan:
Manually with the workspace parts and added integration tests in KWin using
the virtual backend.
BUG:371494
Reviewers: #kwin, graesslin
Subscribers: kwin, plasma-devel, #kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D5928
2017-12-11 09:43:12 +00:00
|
|
|
#include "colorcorrection/manager.h"
|
|
|
|
|
2020-04-29 15:18:41 +00:00
|
|
|
#include <KWaylandServer/outputconfiguration_interface.h>
|
|
|
|
#include <KWaylandServer/outputchangeset.h>
|
2015-03-20 13:41:03 +00:00
|
|
|
|
2020-04-27 10:49:36 +00:00
|
|
|
#include <QX11Info>
|
|
|
|
|
2020-04-29 13:54:06 +00:00
|
|
|
#include <cerrno>
|
|
|
|
|
2015-03-20 13:41:03 +00:00
|
|
|
namespace KWin
|
|
|
|
{
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
Platform::Platform(QObject *parent)
|
2015-03-20 13:41:03 +00:00
|
|
|
: QObject(parent)
|
2016-07-18 08:27:56 +00:00
|
|
|
, m_eglDisplay(EGL_NO_DISPLAY)
|
2015-03-20 13:41:03 +00:00
|
|
|
{
|
2018-04-18 18:08:33 +00:00
|
|
|
setSoftWareCursor(false);
|
2020-04-02 16:18:01 +00:00
|
|
|
m_colorCorrect = new ColorCorrect::Manager(this);
|
|
|
|
connect(Cursors::self(), &Cursors::currentCursorRendered, this, &Platform::cursorRendered);
|
2015-03-20 13:41:03 +00:00
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
Platform::~Platform()
|
2015-03-20 13:41:03 +00:00
|
|
|
{
|
2016-07-18 08:27:56 +00:00
|
|
|
if (m_eglDisplay != EGL_NO_DISPLAY) {
|
|
|
|
eglTerminate(m_eglDisplay);
|
|
|
|
}
|
2015-03-20 13:41:03 +00:00
|
|
|
}
|
|
|
|
|
2016-10-17 14:12:21 +00:00
|
|
|
PlatformCursorImage Platform::cursorImage() const
|
|
|
|
{
|
2020-04-02 16:18:01 +00:00
|
|
|
Cursor* cursor = Cursors::self()->currentCursor();
|
|
|
|
return PlatformCursorImage(cursor->image(), cursor->hotspot());
|
2016-10-17 14:12:21 +00:00
|
|
|
}
|
|
|
|
|
2016-10-20 08:21:54 +00:00
|
|
|
void Platform::hideCursor()
|
|
|
|
{
|
|
|
|
m_hideCursorCounter++;
|
|
|
|
if (m_hideCursorCounter == 1) {
|
|
|
|
doHideCursor();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Platform::doHideCursor()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void Platform::showCursor()
|
|
|
|
{
|
|
|
|
m_hideCursorCounter--;
|
|
|
|
if (m_hideCursorCounter == 0) {
|
|
|
|
doShowCursor();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Platform::doShowCursor()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
Screens *Platform::createScreens(QObject *parent)
|
2015-03-27 06:52:59 +00:00
|
|
|
{
|
|
|
|
Q_UNUSED(parent)
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
OpenGLBackend *Platform::createOpenGLBackend()
|
2015-03-27 07:51:56 +00:00
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
QPainterBackend *Platform::createQPainterBackend()
|
2015-03-27 08:05:03 +00:00
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-09-05 14:59:53 +00:00
|
|
|
void Platform::prepareShutdown()
|
|
|
|
{
|
|
|
|
setOutputsEnabled(false);
|
|
|
|
}
|
|
|
|
|
2016-04-15 11:47:56 +00:00
|
|
|
Edge *Platform::createScreenEdge(ScreenEdges *edges)
|
|
|
|
{
|
|
|
|
return new Edge(edges);
|
|
|
|
}
|
|
|
|
|
2016-08-15 10:00:03 +00:00
|
|
|
void Platform::createPlatformCursor(QObject *parent)
|
|
|
|
{
|
|
|
|
new InputRedirectionCursor(parent);
|
|
|
|
}
|
|
|
|
|
2020-04-29 15:18:41 +00:00
|
|
|
void Platform::requestOutputsChange(KWaylandServer::OutputConfigurationInterface *config)
|
2016-03-10 18:57:07 +00:00
|
|
|
{
|
2019-08-28 18:54:37 +00:00
|
|
|
if (!m_supportsOutputChanges) {
|
|
|
|
qCWarning(KWIN_CORE) << "This backend does not support configuration changes.";
|
|
|
|
config->setFailed();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-04-29 15:18:41 +00:00
|
|
|
using Enablement = KWaylandServer::OutputDeviceInterface::Enablement;
|
2019-08-28 18:54:37 +00:00
|
|
|
|
|
|
|
const auto changes = config->changes();
|
|
|
|
|
|
|
|
//process all non-disabling changes
|
|
|
|
for (auto it = changes.begin(); it != changes.end(); it++) {
|
2020-04-29 15:18:41 +00:00
|
|
|
const KWaylandServer::OutputChangeSet *changeset = it.value();
|
2019-08-28 18:54:37 +00:00
|
|
|
|
|
|
|
auto output = findOutput(it.key()->uuid());
|
|
|
|
if (!output) {
|
|
|
|
qCWarning(KWIN_CORE) << "Could NOT find output matching " << it.key()->uuid();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changeset->enabledChanged() &&
|
|
|
|
changeset->enabled() == Enablement::Enabled) {
|
|
|
|
output->setEnabled(true);
|
|
|
|
}
|
|
|
|
output->applyChanges(changeset);
|
|
|
|
}
|
|
|
|
|
|
|
|
//process any disable requests
|
|
|
|
for (auto it = changes.begin(); it != changes.end(); it++) {
|
2020-04-29 15:18:41 +00:00
|
|
|
const KWaylandServer::OutputChangeSet *changeset = it.value();
|
2019-08-28 18:54:37 +00:00
|
|
|
|
|
|
|
if (changeset->enabledChanged() &&
|
|
|
|
changeset->enabled() == Enablement::Disabled) {
|
|
|
|
if (enabledOutputs().count() == 1) {
|
|
|
|
// TODO: check beforehand this condition and set failed otherwise
|
|
|
|
// TODO: instead create a dummy output?
|
|
|
|
qCWarning(KWIN_CORE) << "Not disabling final screen" << it.key()->uuid();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
auto output = findOutput(it.key()->uuid());
|
|
|
|
if (!output) {
|
|
|
|
qCWarning(KWIN_CORE) << "Could NOT find output matching " << it.key()->uuid();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
output->setEnabled(false);
|
|
|
|
}
|
|
|
|
}
|
2019-08-31 08:27:04 +00:00
|
|
|
emit screens()->changed();
|
2019-08-28 18:54:37 +00:00
|
|
|
config->setApplied();
|
|
|
|
}
|
|
|
|
|
2020-08-18 18:42:45 +00:00
|
|
|
AbstractOutput *Platform::findOutput(int screenId)
|
|
|
|
{
|
|
|
|
return enabledOutputs().value(screenId);
|
|
|
|
}
|
|
|
|
|
2019-08-28 18:54:37 +00:00
|
|
|
AbstractOutput *Platform::findOutput(const QByteArray &uuid)
|
|
|
|
{
|
|
|
|
const auto outs = outputs();
|
|
|
|
auto it = std::find_if(outs.constBegin(), outs.constEnd(),
|
|
|
|
[uuid](AbstractOutput *output) {
|
|
|
|
return output->uuid() == uuid; }
|
|
|
|
);
|
|
|
|
if (it != outs.constEnd()) {
|
|
|
|
return *it;
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::setSoftWareCursor(bool set)
|
2015-04-01 13:36:40 +00:00
|
|
|
{
|
2018-04-18 18:08:33 +00:00
|
|
|
if (qEnvironmentVariableIsSet("KWIN_FORCE_SW_CURSOR")) {
|
|
|
|
set = true;
|
|
|
|
}
|
2015-04-01 13:36:40 +00:00
|
|
|
if (m_softWareCursor == set) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_softWareCursor = set;
|
|
|
|
if (m_softWareCursor) {
|
2020-04-02 16:18:01 +00:00
|
|
|
connect(Cursors::self(), &Cursors::positionChanged, this, &Platform::triggerCursorRepaint);
|
|
|
|
connect(Cursors::self(), &Cursors::currentCursorChanged, this, &Platform::triggerCursorRepaint);
|
2015-04-01 13:36:40 +00:00
|
|
|
} else {
|
2020-04-02 16:18:01 +00:00
|
|
|
disconnect(Cursors::self(), &Cursors::positionChanged, this, &Platform::triggerCursorRepaint);
|
|
|
|
disconnect(Cursors::self(), &Cursors::currentCursorChanged, this, &Platform::triggerCursorRepaint);
|
2015-04-01 13:36:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::triggerCursorRepaint()
|
2015-04-01 13:36:40 +00:00
|
|
|
{
|
2016-02-23 11:29:05 +00:00
|
|
|
if (!Compositor::self()) {
|
2015-04-01 13:36:40 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-06-28 06:33:47 +00:00
|
|
|
Compositor::self()->addRepaint(m_cursor.lastRenderedGeometry);
|
2020-04-02 16:18:01 +00:00
|
|
|
Compositor::self()->addRepaint(Cursors::self()->currentCursor()->geometry());
|
2015-04-01 13:36:40 +00:00
|
|
|
}
|
|
|
|
|
2020-04-02 16:18:01 +00:00
|
|
|
void Platform::cursorRendered(const QRect &geometry)
|
2015-04-01 13:36:40 +00:00
|
|
|
{
|
2016-02-23 11:29:05 +00:00
|
|
|
if (m_softWareCursor) {
|
2020-04-02 16:18:01 +00:00
|
|
|
m_cursor.lastRenderedGeometry = geometry;
|
2016-02-23 11:29:05 +00:00
|
|
|
}
|
2015-04-01 13:36:40 +00:00
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::keyboardKeyPressed(quint32 key, quint32 time)
|
2015-05-05 08:44:46 +00:00
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->processKeyboardKey(key, InputRedirection::KeyboardKeyPressed, time);
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::keyboardKeyReleased(quint32 key, quint32 time)
|
2015-05-05 08:44:46 +00:00
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->processKeyboardKey(key, InputRedirection::KeyboardKeyReleased, time);
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::keyboardModifiers(uint32_t modsDepressed, uint32_t modsLatched, uint32_t modsLocked, uint32_t group)
|
2015-05-05 08:44:46 +00:00
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->processKeyboardModifiers(modsDepressed, modsLatched, modsLocked, group);
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::keymapChange(int fd, uint32_t size)
|
2015-05-05 08:44:46 +00:00
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->processKeymapChange(fd, size);
|
|
|
|
}
|
|
|
|
|
Send axis_source, axis_discrete, and axis_stop
Summary:
So far KWin didn't send axis_source, axis_discrete, and axis_stop. Even
though most of those events are optional, clients need them to work as
expected. For example, one needs axis_source and axis_stop to implement
kinetic scrolling; Xwayland needs axis_discrete to prevent multiple
scroll events when the compositor sends axis deltas greater than 10, etc.
BUG: 404152
FIXED-IN: 5.17.0
Test Plan:
* Content of a webpage in Firefox is moved by one line per each mouse
wheel "click";
* Scrolled gedit using 2 fingers on GNOME Shell, sway, and KDE Plasma;
in all three cases wayland debug looked the same (except diagonal scroll
motions).
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D19000
2019-02-12 09:14:51 +00:00
|
|
|
void Platform::pointerAxisHorizontal(qreal delta, quint32 time, qint32 discreteDelta, InputRedirection::PointerAxisSource source)
|
2015-05-05 08:44:46 +00:00
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
Send axis_source, axis_discrete, and axis_stop
Summary:
So far KWin didn't send axis_source, axis_discrete, and axis_stop. Even
though most of those events are optional, clients need them to work as
expected. For example, one needs axis_source and axis_stop to implement
kinetic scrolling; Xwayland needs axis_discrete to prevent multiple
scroll events when the compositor sends axis deltas greater than 10, etc.
BUG: 404152
FIXED-IN: 5.17.0
Test Plan:
* Content of a webpage in Firefox is moved by one line per each mouse
wheel "click";
* Scrolled gedit using 2 fingers on GNOME Shell, sway, and KDE Plasma;
in all three cases wayland debug looked the same (except diagonal scroll
motions).
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D19000
2019-02-12 09:14:51 +00:00
|
|
|
input()->processPointerAxis(InputRedirection::PointerAxisHorizontal, delta, discreteDelta, source, time);
|
2015-05-05 08:44:46 +00:00
|
|
|
}
|
|
|
|
|
Send axis_source, axis_discrete, and axis_stop
Summary:
So far KWin didn't send axis_source, axis_discrete, and axis_stop. Even
though most of those events are optional, clients need them to work as
expected. For example, one needs axis_source and axis_stop to implement
kinetic scrolling; Xwayland needs axis_discrete to prevent multiple
scroll events when the compositor sends axis deltas greater than 10, etc.
BUG: 404152
FIXED-IN: 5.17.0
Test Plan:
* Content of a webpage in Firefox is moved by one line per each mouse
wheel "click";
* Scrolled gedit using 2 fingers on GNOME Shell, sway, and KDE Plasma;
in all three cases wayland debug looked the same (except diagonal scroll
motions).
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D19000
2019-02-12 09:14:51 +00:00
|
|
|
void Platform::pointerAxisVertical(qreal delta, quint32 time, qint32 discreteDelta, InputRedirection::PointerAxisSource source)
|
2015-05-05 08:44:46 +00:00
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
Send axis_source, axis_discrete, and axis_stop
Summary:
So far KWin didn't send axis_source, axis_discrete, and axis_stop. Even
though most of those events are optional, clients need them to work as
expected. For example, one needs axis_source and axis_stop to implement
kinetic scrolling; Xwayland needs axis_discrete to prevent multiple
scroll events when the compositor sends axis deltas greater than 10, etc.
BUG: 404152
FIXED-IN: 5.17.0
Test Plan:
* Content of a webpage in Firefox is moved by one line per each mouse
wheel "click";
* Scrolled gedit using 2 fingers on GNOME Shell, sway, and KDE Plasma;
in all three cases wayland debug looked the same (except diagonal scroll
motions).
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D19000
2019-02-12 09:14:51 +00:00
|
|
|
input()->processPointerAxis(InputRedirection::PointerAxisVertical, delta, discreteDelta, source, time);
|
2015-05-05 08:44:46 +00:00
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::pointerButtonPressed(quint32 button, quint32 time)
|
2015-05-05 08:44:46 +00:00
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->processPointerButton(button, InputRedirection::PointerButtonPressed, time);
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::pointerButtonReleased(quint32 button, quint32 time)
|
2015-05-05 08:44:46 +00:00
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->processPointerButton(button, InputRedirection::PointerButtonReleased, time);
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::pointerMotion(const QPointF &position, quint32 time)
|
2015-05-05 08:44:46 +00:00
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->processPointerMotion(position, time);
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::touchCancel()
|
2015-05-05 08:44:46 +00:00
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->cancelTouch();
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::touchDown(qint32 id, const QPointF &pos, quint32 time)
|
2015-05-05 08:44:46 +00:00
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->processTouchDown(id, pos, time);
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::touchFrame()
|
2015-05-05 08:44:46 +00:00
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->touchFrame();
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::touchMotion(qint32 id, const QPointF &pos, quint32 time)
|
2015-05-05 08:44:46 +00:00
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->processTouchMotion(id, pos, time);
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::touchUp(qint32 id, quint32 time)
|
2015-05-05 08:44:46 +00:00
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->processTouchUp(id, time);
|
|
|
|
}
|
|
|
|
|
2017-03-15 16:56:08 +00:00
|
|
|
void Platform::processSwipeGestureBegin(int fingerCount, quint32 time)
|
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->pointer()->processSwipeGestureBegin(fingerCount, time);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Platform::processSwipeGestureUpdate(const QSizeF &delta, quint32 time)
|
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->pointer()->processSwipeGestureUpdate(delta, time);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Platform::processSwipeGestureEnd(quint32 time)
|
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->pointer()->processSwipeGestureEnd(time);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Platform::processSwipeGestureCancelled(quint32 time)
|
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->pointer()->processSwipeGestureCancelled(time);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Platform::processPinchGestureBegin(int fingerCount, quint32 time)
|
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->pointer()->processPinchGestureBegin(fingerCount, time);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Platform::processPinchGestureUpdate(qreal scale, qreal angleDelta, const QSizeF &delta, quint32 time)
|
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->pointer()->processPinchGestureUpdate(scale, angleDelta, delta, time);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Platform::processPinchGestureEnd(quint32 time)
|
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->pointer()->processPinchGestureEnd(time);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Platform::processPinchGestureCancelled(quint32 time)
|
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->pointer()->processPinchGestureCancelled(time);
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::repaint(const QRect &rect)
|
2015-05-05 08:54:13 +00:00
|
|
|
{
|
|
|
|
if (!Compositor::self()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Compositor::self()->addRepaint(rect);
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::setReady(bool ready)
|
2015-05-05 17:02:52 +00:00
|
|
|
{
|
|
|
|
if (m_ready == ready) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_ready = ready;
|
|
|
|
emit readyChanged(m_ready);
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::warpPointer(const QPointF &globalPos)
|
2015-06-05 17:34:03 +00:00
|
|
|
{
|
|
|
|
Q_UNUSED(globalPos)
|
|
|
|
}
|
|
|
|
|
2020-10-12 06:50:55 +00:00
|
|
|
bool Platform::supportsSurfacelessContext() const
|
2015-08-18 06:40:35 +00:00
|
|
|
{
|
2020-10-16 16:30:37 +00:00
|
|
|
Compositor *compositor = Compositor::self();
|
|
|
|
if (Q_UNLIKELY(!compositor)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (Scene *scene = compositor->scene()) {
|
|
|
|
return scene->supportsSurfacelessContext();
|
2016-11-17 06:51:04 +00:00
|
|
|
}
|
|
|
|
return false;
|
2015-08-18 06:40:35 +00:00
|
|
|
}
|
|
|
|
|
2020-10-15 09:27:00 +00:00
|
|
|
bool Platform::supportsNativeFence() const
|
|
|
|
{
|
|
|
|
if (Compositor *compositor = Compositor::self()) {
|
|
|
|
return compositor->scene()->supportsNativeFence();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-07-18 08:27:56 +00:00
|
|
|
EGLDisplay KWin::Platform::sceneEglDisplay() const
|
2015-08-18 06:35:34 +00:00
|
|
|
{
|
2016-07-18 08:27:56 +00:00
|
|
|
return m_eglDisplay;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Platform::setSceneEglDisplay(EGLDisplay display)
|
|
|
|
{
|
|
|
|
m_eglDisplay = display;
|
2015-08-18 06:35:34 +00:00
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
QSize Platform::screenSize() const
|
2015-11-17 09:32:06 +00:00
|
|
|
{
|
|
|
|
return QSize();
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
QVector<QRect> Platform::screenGeometries() const
|
2015-11-20 15:11:35 +00:00
|
|
|
{
|
|
|
|
return QVector<QRect>({QRect(QPoint(0, 0), screenSize())});
|
|
|
|
}
|
|
|
|
|
2016-10-25 23:36:02 +00:00
|
|
|
QVector<qreal> Platform::screenScales() const
|
|
|
|
{
|
|
|
|
return QVector<qreal>({1});
|
|
|
|
}
|
|
|
|
|
2016-05-09 14:41:37 +00:00
|
|
|
bool Platform::requiresCompositing() const
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-05-09 15:32:43 +00:00
|
|
|
bool Platform::compositingPossible() const
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Platform::compositingNotPossibleReason() const
|
|
|
|
{
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Platform::openGLCompositingIsBroken() const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-05-10 08:34:09 +00:00
|
|
|
void Platform::createOpenGLSafePoint(OpenGLSafePoint safePoint)
|
|
|
|
{
|
|
|
|
Q_UNUSED(safePoint)
|
|
|
|
}
|
|
|
|
|
2016-11-15 09:22:56 +00:00
|
|
|
void Platform::startInteractiveWindowSelection(std::function<void(KWin::Toplevel*)> callback, const QByteArray &cursorName)
|
|
|
|
{
|
2016-11-15 13:23:51 +00:00
|
|
|
if (!input()) {
|
|
|
|
callback(nullptr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->startInteractiveWindowSelection(callback, cursorName);
|
2016-11-15 09:22:56 +00:00
|
|
|
}
|
|
|
|
|
2016-11-23 14:53:17 +00:00
|
|
|
void Platform::startInteractivePositionSelection(std::function<void(const QPoint &)> callback)
|
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
callback(QPoint(-1, -1));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->startInteractivePositionSelection(callback);
|
|
|
|
}
|
|
|
|
|
2017-01-17 06:12:44 +00:00
|
|
|
void Platform::setupActionForGlobalAccel(QAction *action)
|
|
|
|
{
|
|
|
|
Q_UNUSED(action)
|
|
|
|
}
|
|
|
|
|
2017-08-07 15:54:56 +00:00
|
|
|
OverlayWindow *Platform::createOverlayWindow()
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2020-04-27 10:49:36 +00:00
|
|
|
static quint32 monotonicTime()
|
|
|
|
{
|
|
|
|
timespec ts;
|
|
|
|
|
|
|
|
const int result = clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
|
|
if (result)
|
|
|
|
qCWarning(KWIN_CORE, "Failed to query monotonic time: %s", strerror(errno));
|
|
|
|
|
|
|
|
return ts.tv_sec * 1000 + ts.tv_nsec / 1000000L;
|
|
|
|
}
|
|
|
|
|
2017-08-24 14:53:40 +00:00
|
|
|
void Platform::updateXTime()
|
|
|
|
{
|
2020-04-27 10:49:36 +00:00
|
|
|
switch (kwinApp()->operationMode()) {
|
|
|
|
case Application::OperationModeX11:
|
|
|
|
kwinApp()->setX11Time(QX11Info::getTimestamp(), Application::TimestampUpdate::Always);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Application::OperationModeXwayland:
|
|
|
|
kwinApp()->setX11Time(monotonicTime(), Application::TimestampUpdate::Always);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
// Do not update the current X11 time stamp if it's the Wayland only session.
|
|
|
|
break;
|
|
|
|
}
|
2017-08-24 14:53:40 +00:00
|
|
|
}
|
|
|
|
|
2017-08-21 09:59:52 +00:00
|
|
|
OutlineVisual *Platform::createOutline(Outline *outline)
|
|
|
|
{
|
|
|
|
if (Compositor::compositing()) {
|
|
|
|
return new CompositedOutlineVisual(outline);
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-08-20 20:15:21 +00:00
|
|
|
Decoration::Renderer *Platform::createDecorationRenderer(Decoration::DecoratedClientImpl *client)
|
|
|
|
{
|
2019-09-05 16:06:03 +00:00
|
|
|
if (Compositor::self()->scene()) {
|
2017-09-01 18:58:30 +00:00
|
|
|
return Compositor::self()->scene()->createDecorationRenderer(client);
|
2017-08-20 20:15:21 +00:00
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-08-21 06:53:56 +00:00
|
|
|
void Platform::invertScreen()
|
|
|
|
{
|
|
|
|
if (effects) {
|
|
|
|
if (Effect *inverter = static_cast<EffectsHandlerImpl*>(effects)->provides(Effect::ScreenInversion)) {
|
|
|
|
qCDebug(KWIN_CORE) << "inverting screen using Effect plugin";
|
|
|
|
QMetaObject::invokeMethod(inverter, "toggleScreenInversion", Qt::DirectConnection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-23 18:21:26 +00:00
|
|
|
void Platform::createEffectsHandler(Compositor *compositor, Scene *scene)
|
|
|
|
{
|
|
|
|
new EffectsHandlerImpl(compositor, scene);
|
|
|
|
}
|
|
|
|
|
2017-11-07 19:12:51 +00:00
|
|
|
QString Platform::supportInformation() const
|
|
|
|
{
|
|
|
|
return QStringLiteral("Name: %1\n").arg(metaObject()->className());
|
|
|
|
}
|
|
|
|
|
2020-10-16 14:57:35 +00:00
|
|
|
EGLContext Platform::sceneEglGlobalShareContext() const
|
|
|
|
{
|
|
|
|
return m_globalShareContext;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Platform::setSceneEglGlobalShareContext(EGLContext context)
|
|
|
|
{
|
|
|
|
m_globalShareContext = context;
|
|
|
|
}
|
|
|
|
|
2015-03-20 13:41:03 +00:00
|
|
|
}
|