/******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2015 Martin Gräßlin Copyright (C) 2019 Vlad Zagorodniy 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 . *********************************************************************/ #include "integration.h" #include "backingstore.h" #include "offscreensurface.h" #include "screen.h" #include "sharingplatformcontext.h" #include "window.h" #include "../../main.h" #include "../../platform.h" #include "../../screens.h" #include "../../virtualkeyboard.h" #include #include #include #include #include #include #include #include #include namespace KWin { namespace QPA { Integration::Integration() : QObject() , QPlatformIntegration() , m_fontDb(new QGenericUnixFontDatabase()) , m_inputContext() { } Integration::~Integration() = default; bool Integration::hasCapability(Capability cap) const { switch (cap) { case ThreadedPixmaps: return true; case OpenGL: return true; case ThreadedOpenGL: return false; case BufferQueueingOpenGL: return false; case MultipleWindows: case NonFullScreenWindows: return true; case RasterGLSurface: return false; default: return QPlatformIntegration::hasCapability(cap); } } void Integration::initialize() { connect(kwinApp(), &Application::screensCreated, this, [this] { connect(screens(), &Screens::changed, this, &Integration::initScreens); initScreens(); } ); QPlatformIntegration::initialize(); auto dummyScreen = new Screen(-1); #if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)) QWindowSystemInterface::handleScreenAdded(dummyScreen); #else screenAdded(dummyScreen); #endif m_screens << dummyScreen; m_inputContext.reset(QPlatformInputContextFactory::create(QStringLiteral("qtvirtualkeyboard"))); qunsetenv("QT_IM_MODULE"); if (!m_inputContext.isNull()) { connect(qApp, &QGuiApplication::focusObjectChanged, this, [this] { if (VirtualKeyboard::self() && qApp->focusObject() != VirtualKeyboard::self()) { m_inputContext->setFocusObject(VirtualKeyboard::self()); } } ); connect(kwinApp(), &Application::workspaceCreated, this, [this] { if (VirtualKeyboard::self()) { m_inputContext->setFocusObject(VirtualKeyboard::self()); } } ); connect(qApp->inputMethod(), &QInputMethod::visibleChanged, this, [] { if (qApp->inputMethod()->isVisible()) { if (QWindow *w = VirtualKeyboard::self()->inputPanel()) { QWindowSystemInterface::handleWindowActivated(w, Qt::ActiveWindowFocusReason); } } } ); } } QAbstractEventDispatcher *Integration::createEventDispatcher() const { return new QUnixEventDispatcherQPA; } QPlatformBackingStore *Integration::createPlatformBackingStore(QWindow *window) const { return new BackingStore(window); } QPlatformWindow *Integration::createPlatformWindow(QWindow *window) const { return new Window(window); } QPlatformOffscreenSurface *Integration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const { return new OffscreenSurface(surface); } QPlatformFontDatabase *Integration::fontDatabase() const { return m_fontDb; } QPlatformTheme *Integration::createPlatformTheme(const QString &name) const { return QGenericUnixTheme::createUnixTheme(name); } QStringList Integration::themeNames() const { if (qEnvironmentVariableIsSet("KDE_FULL_SESSION")) { return QStringList({QStringLiteral("kde")}); } return QStringList({QLatin1String(QGenericUnixTheme::name)}); } QPlatformOpenGLContext *Integration::createPlatformOpenGLContext(QOpenGLContext *context) const { if (kwinApp()->platform()->supportsQpaContext()) { return new SharingPlatformContext(context); } if (kwinApp()->platform()->sceneEglDisplay() != EGL_NO_DISPLAY) { auto s = kwinApp()->platform()->sceneEglSurface(); if (s != EGL_NO_SURFACE) { // try a SharingPlatformContext with a created surface return new SharingPlatformContext(context, s, kwinApp()->platform()->sceneEglConfig()); } } return nullptr; } void Integration::initScreens() { QVector newScreens; newScreens.reserve(qMax(screens()->count(), 1)); for (int i = 0; i < screens()->count(); i++) { auto screen = new Screen(i); #if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)) QWindowSystemInterface::handleScreenAdded(screen); #else screenAdded(screen); #endif newScreens << screen; } if (newScreens.isEmpty()) { auto dummyScreen = new Screen(-1); #if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)) QWindowSystemInterface::handleScreenAdded(dummyScreen); #else screenAdded(dummyScreen); #endif newScreens << dummyScreen; } while (!m_screens.isEmpty()) { #if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)) QWindowSystemInterface::handleScreenRemoved(m_screens.takeLast()); #else destroyScreen(m_screens.takeLast()); #endif } m_screens = newScreens; } QPlatformInputContext *Integration::inputContext() const { return m_inputContext.data(); } } }