2015-03-20 13:41:03 +00:00
|
|
|
/********************************************************************
|
|
|
|
KWin - the KDE window manager
|
|
|
|
This file is part of the KDE project.
|
|
|
|
|
|
|
|
Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org>
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*********************************************************************/
|
2016-04-07 07:24:17 +00:00
|
|
|
#include "platform.h"
|
2015-04-02 12:37:23 +00:00
|
|
|
#include <config-kwin.h>
|
2015-08-18 06:35:34 +00:00
|
|
|
#include "abstract_egl_backend.h"
|
2015-04-01 13:36:40 +00:00
|
|
|
#include "composite.h"
|
|
|
|
#include "cursor.h"
|
2015-05-05 08:44:46 +00:00
|
|
|
#include "input.h"
|
2016-02-23 11:29:05 +00:00
|
|
|
#include "pointer_input.h"
|
2015-08-18 06:35:34 +00:00
|
|
|
#include "scene_opengl.h"
|
2016-04-15 11:47:56 +00:00
|
|
|
#include "screenedge.h"
|
2015-03-20 13:41:03 +00:00
|
|
|
#include "wayland_server.h"
|
|
|
|
|
|
|
|
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
|
|
|
{
|
|
|
|
}
|
|
|
|
|
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-04-07 07:18:10 +00:00
|
|
|
QImage Platform::softwareCursor() const
|
2015-03-20 13:41:03 +00:00
|
|
|
{
|
2016-02-23 11:29:05 +00:00
|
|
|
return input()->pointer()->cursorImage();
|
2015-03-20 13:41:03 +00:00
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
QPoint Platform::softwareCursorHotspot() const
|
2015-03-20 13:41:03 +00:00
|
|
|
{
|
2016-02-23 11:29:05 +00:00
|
|
|
return input()->pointer()->cursorHotSpot();
|
2015-03-20 13:41:03 +00:00
|
|
|
}
|
|
|
|
|
2016-10-17 14:12:21 +00:00
|
|
|
PlatformCursorImage Platform::cursorImage() const
|
|
|
|
{
|
|
|
|
return PlatformCursorImage(softwareCursor(), softwareCursorHotspot());
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::configurationChangeRequested(KWayland::Server::OutputConfigurationInterface *config)
|
2016-03-10 18:57:07 +00:00
|
|
|
{
|
|
|
|
Q_UNUSED(config)
|
|
|
|
qCWarning(KWIN_CORE) << "This backend does not support configuration changes.";
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::setSoftWareCursor(bool set)
|
2015-04-01 13:36:40 +00:00
|
|
|
{
|
|
|
|
if (m_softWareCursor == set) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_softWareCursor = set;
|
|
|
|
if (m_softWareCursor) {
|
2016-04-07 07:18:10 +00:00
|
|
|
connect(Cursor::self(), &Cursor::posChanged, this, &Platform::triggerCursorRepaint);
|
2016-06-28 06:33:47 +00:00
|
|
|
connect(this, &Platform::cursorChanged, this, &Platform::triggerCursorRepaint);
|
2015-04-01 13:36:40 +00:00
|
|
|
} else {
|
2016-04-07 07:18:10 +00:00
|
|
|
disconnect(Cursor::self(), &Cursor::posChanged, this, &Platform::triggerCursorRepaint);
|
2016-06-28 06:33:47 +00:00
|
|
|
disconnect(this, &Platform::cursorChanged, 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);
|
|
|
|
Compositor::self()->addRepaint(QRect(Cursor::pos() - softwareCursorHotspot(), softwareCursor().size()));
|
2015-04-01 13:36:40 +00:00
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::markCursorAsRendered()
|
2015-04-01 13:36:40 +00:00
|
|
|
{
|
2016-02-23 11:29:05 +00:00
|
|
|
if (m_softWareCursor) {
|
2016-06-28 06:33:47 +00:00
|
|
|
m_cursor.lastRenderedGeometry = QRect(Cursor::pos() - softwareCursorHotspot(), softwareCursor().size());
|
2016-02-23 11:29:05 +00:00
|
|
|
}
|
|
|
|
if (input()->pointer()) {
|
|
|
|
input()->pointer()->markCursorAsRendered();
|
|
|
|
}
|
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);
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::pointerAxisHorizontal(qreal delta, quint32 time)
|
2015-05-05 08:44:46 +00:00
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->processPointerAxis(InputRedirection::PointerAxisHorizontal, delta, time);
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
void Platform::pointerAxisVertical(qreal delta, quint32 time)
|
2015-05-05 08:44:46 +00:00
|
|
|
{
|
|
|
|
if (!input()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
input()->processPointerAxis(InputRedirection::PointerAxisVertical, delta, time);
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2016-04-07 07:18:10 +00:00
|
|
|
bool Platform::supportsQpaContext() const
|
2015-08-18 06:40:35 +00:00
|
|
|
{
|
2016-11-17 06:51:04 +00:00
|
|
|
if (Compositor *c = Compositor::self()) {
|
|
|
|
if (SceneOpenGL *s = dynamic_cast<SceneOpenGL*>(c->scene())) {
|
|
|
|
return s->backend()->hasExtension(QByteArrayLiteral("EGL_KHR_surfaceless_context"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2015-08-18 06:40:35 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
EGLContext Platform::sceneEglContext() const
|
2015-08-18 06:35:34 +00:00
|
|
|
{
|
|
|
|
if (Compositor *c = Compositor::self()) {
|
|
|
|
if (SceneOpenGL *s = dynamic_cast<SceneOpenGL*>(c->scene())) {
|
|
|
|
return static_cast<AbstractEglBackend*>(s->backend())->context();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return EGL_NO_CONTEXT;
|
|
|
|
}
|
|
|
|
|
2016-07-18 09:17:54 +00:00
|
|
|
EGLSurface Platform::sceneEglSurface() const
|
|
|
|
{
|
|
|
|
if (Compositor *c = Compositor::self()) {
|
|
|
|
if (SceneOpenGL *s = dynamic_cast<SceneOpenGL*>(c->scene())) {
|
|
|
|
return static_cast<AbstractEglBackend*>(s->backend())->surface();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return EGL_NO_SURFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EGLConfig Platform::sceneEglConfig() const
|
|
|
|
{
|
|
|
|
if (Compositor *c = Compositor::self()) {
|
|
|
|
if (SceneOpenGL *s = dynamic_cast<SceneOpenGL*>(c->scene())) {
|
|
|
|
return static_cast<AbstractEglBackend*>(s->backend())->config();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
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-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);
|
|
|
|
}
|
|
|
|
|
2015-03-20 13:41:03 +00:00
|
|
|
}
|