[wayland] Add a QPA plugin for kwin_wayland
This introduces an own QPA plugin for KWin. QtWayland's plugin is not a good solution for KWin as QtWayland is meant for Wayland clients and not for a Wayland server. Given that it makes more sense to have a very minimal QPA plugin which supports the use cases we actually have. With our own QPA plugin we should be able to improve the following areas: * no need to create Wayland server before QApplication * Qt::BypassWindowManagerHint can be supported * no workaround for creating OpenGL context in main thread * sharing OpenGL context with Qt * OpenGL context for Qt on libhybris backend The plugin supports so far the following features: * creating a QPlatformWindow using KWayland::Client (ShellSurface) * creating a QPlatformBackingStore using a ShmPool * creating a QPlatformOpenGLContext with Wayland::EGL * or creating a QPlatformOpenGLContext which shares with KWin's scene * creating a QPlatformScreen for each KWayland::Client::Output * QPlatformNativeInterface compatible to QtWayland
This commit is contained in:
parent
79317717c8
commit
26b3569a0b
23 changed files with 1792 additions and 0 deletions
|
@ -211,6 +211,21 @@ set_package_properties(X11_XCB PROPERTIES
|
|||
PURPOSE "Required for building X11 windowed backend of kwin_wayland"
|
||||
TYPE OPTIONAL)
|
||||
|
||||
# dependencies for QPA plugin
|
||||
find_package(Qt5PlatformSupport REQUIRED)
|
||||
find_package(Freetype REQUIRED)
|
||||
set_package_properties(Freetype PROPERTIES DESCRIPTION "A font rendering engine"
|
||||
URL "http://www.freetype.org"
|
||||
TYPE REQUIRED
|
||||
PURPOSE "Needed for KWin's QPA plugin."
|
||||
)
|
||||
find_package(Fontconfig REQUIRED)
|
||||
set_package_properties(Fontconfig PROPERTIES DESCRIPTION "Font access configuration library"
|
||||
URL "http://www.freedesktop.org/wiki/Software/fontconfig"
|
||||
TYPE REQUIRED
|
||||
PURPOSE "Needed for KWin's QPA plugin."
|
||||
)
|
||||
|
||||
########### configure tests ###############
|
||||
include(CMakeDependentOption)
|
||||
|
||||
|
|
50
cmake/modules/FindFontconfig.cmake
Normal file
50
cmake/modules/FindFontconfig.cmake
Normal file
|
@ -0,0 +1,50 @@
|
|||
# - Try to find the Fontconfig
|
||||
# Once done this will define
|
||||
#
|
||||
# FONTCONFIG_FOUND - system has Fontconfig
|
||||
# FONTCONFIG_INCLUDE_DIR - The include directory to use for the fontconfig headers
|
||||
# FONTCONFIG_LIBRARIES - Link these to use FONTCONFIG
|
||||
# FONTCONFIG_DEFINITIONS - Compiler switches required for using FONTCONFIG
|
||||
|
||||
# Copyright (c) 2006,2007 Laurent Montel, <montel@kde.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
|
||||
if (FONTCONFIG_LIBRARIES AND FONTCONFIG_INCLUDE_DIR)
|
||||
|
||||
# in cache already
|
||||
set(FONTCONFIG_FOUND TRUE)
|
||||
|
||||
else (FONTCONFIG_LIBRARIES AND FONTCONFIG_INCLUDE_DIR)
|
||||
|
||||
if (NOT WIN32)
|
||||
# use pkg-config to get the directories and then use these values
|
||||
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PC_FONTCONFIG QUIET fontconfig)
|
||||
|
||||
set(FONTCONFIG_DEFINITIONS ${PC_FONTCONFIG_CFLAGS_OTHER})
|
||||
endif (NOT WIN32)
|
||||
|
||||
find_path(FONTCONFIG_INCLUDE_DIR fontconfig/fontconfig.h
|
||||
PATHS
|
||||
${PC_FONTCONFIG_INCLUDEDIR}
|
||||
${PC_FONTCONFIG_INCLUDE_DIRS}
|
||||
/usr/X11/include
|
||||
)
|
||||
|
||||
find_library(FONTCONFIG_LIBRARIES NAMES fontconfig
|
||||
PATHS
|
||||
${PC_FONTCONFIG_LIBDIR}
|
||||
${PC_FONTCONFIG_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Fontconfig DEFAULT_MSG FONTCONFIG_LIBRARIES FONTCONFIG_INCLUDE_DIR )
|
||||
|
||||
mark_as_advanced(FONTCONFIG_LIBRARIES FONTCONFIG_INCLUDE_DIR)
|
||||
|
||||
endif (FONTCONFIG_LIBRARIES AND FONTCONFIG_INCLUDE_DIR)
|
||||
|
121
cmake/modules/FindQt5PlatformSupport.cmake
Normal file
121
cmake/modules/FindQt5PlatformSupport.cmake
Normal file
|
@ -0,0 +1,121 @@
|
|||
#.rst:
|
||||
# FindQt5PlatformSupport
|
||||
# -------
|
||||
#
|
||||
# Try to find Qt5PlatformSupport on a Unix system.
|
||||
#
|
||||
# This will define the following variables:
|
||||
#
|
||||
# ``Qt5PlatformSupport_FOUND``
|
||||
# True if (the requested version of) Qt5PlatformSupport is available
|
||||
# ``Qt5PlatformSupport_VERSION``
|
||||
# The version of Qt5PlatformSupport
|
||||
# ``Qt5PlatformSupport_LIBRARIES``
|
||||
# This can be passed to target_link_libraries() instead of the ``Qt5PlatformSupport::Qt5PlatformSupport``
|
||||
# target
|
||||
# ``Qt5PlatformSupport_INCLUDE_DIRS``
|
||||
# This should be passed to target_include_directories() if the target is not
|
||||
# used for linking
|
||||
# ``Qt5PlatformSupport_DEFINITIONS``
|
||||
# This should be passed to target_compile_options() if the target is not
|
||||
# used for linking
|
||||
#
|
||||
# If ``Qt5PlatformSupport_FOUND`` is TRUE, it will also define the following imported target:
|
||||
#
|
||||
# ``Qt5PlatformSupport::Qt5PlatformSupport``
|
||||
# The Qt5PlatformSupport library
|
||||
#
|
||||
# In general we recommend using the imported target, as it is easier to use.
|
||||
# Bear in mind, however, that if the target is in the link interface of an
|
||||
# exported library, it must be made available by the package config file.
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2014 Alex Merry <alex.merry@kde.org>
|
||||
# Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. The name of the author may not be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#=============================================================================
|
||||
|
||||
if(CMAKE_VERSION VERSION_LESS 2.8.12)
|
||||
message(FATAL_ERROR "CMake 2.8.12 is required by FindQt5PlatformSupport.cmake")
|
||||
endif()
|
||||
if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12)
|
||||
message(AUTHOR_WARNING "Your project should require at least CMake 2.8.12 to use FindQt5PlatformSupport.cmake")
|
||||
endif()
|
||||
|
||||
# Use pkg-config to get the directories and then use these values
|
||||
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PKG_Qt5PlatformSupport QUIET Qt5PlatformSupport)
|
||||
|
||||
set(Qt5PlatformSupport_DEFINITIONS ${PKG_Qt5PlatformSupport_CFLAGS_OTHER})
|
||||
set(Qt5PlatformSupport_VERSION ${PKG_Qt5PlatformSupport_VERSION})
|
||||
|
||||
find_path(Qt5PlatformSupport_INCLUDE_DIR
|
||||
NAMES
|
||||
QtPlatformSupport/private/qfontconfigdatabase_p.h
|
||||
HINTS
|
||||
${PKG_Qt5PlatformSupport_INCLUDE_DIRS}/QtPlatformSupport/${PKG_Qt5PlatformSupport_VERSION}/
|
||||
)
|
||||
find_library(Qt5PlatformSupport_LIBRARY
|
||||
NAMES
|
||||
Qt5PlatformSupport
|
||||
HINTS
|
||||
${PKG_Qt5PlatformSupport_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Qt5PlatformSupport
|
||||
FOUND_VAR
|
||||
Qt5PlatformSupport_FOUND
|
||||
REQUIRED_VARS
|
||||
Qt5PlatformSupport_LIBRARY
|
||||
Qt5PlatformSupport_INCLUDE_DIR
|
||||
VERSION_VAR
|
||||
Qt5PlatformSupport_VERSION
|
||||
)
|
||||
|
||||
if(Qt5PlatformSupport_FOUND AND NOT TARGET Qt5PlatformSupport::Qt5PlatformSupport)
|
||||
add_library(Qt5PlatformSupport::Qt5PlatformSupport UNKNOWN IMPORTED)
|
||||
set_target_properties(Qt5PlatformSupport::Qt5PlatformSupport PROPERTIES
|
||||
IMPORTED_LOCATION "${Qt5PlatformSupport_LIBRARY}"
|
||||
INTERFACE_COMPILE_OPTIONS "${Qt5PlatformSupport_DEFINITIONS}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${Qt5PlatformSupport_INCLUDE_DIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(Qt5PlatformSupport_LIBRARY Qt5PlatformSupport_INCLUDE_DIR)
|
||||
|
||||
# compatibility variables
|
||||
set(Qt5PlatformSupport_LIBRARIES ${Qt5PlatformSupport_LIBRARY})
|
||||
set(Qt5PlatformSupport_INCLUDE_DIRS ${Qt5PlatformSupport_INCLUDE_DIR})
|
||||
set(Qt5PlatformSupport_VERSION_STRING ${Qt5PlatformSupport_VERSION})
|
||||
|
||||
|
||||
include(FeatureSummary)
|
||||
set_package_properties(Qt5PlatformSupport PROPERTIES
|
||||
URL "http://www.qt.io"
|
||||
DESCRIPTION "Qt PlatformSupport module."
|
||||
)
|
||||
|
|
@ -1 +1,2 @@
|
|||
add_subdirectory(kglobalaccel)
|
||||
add_subdirectory(qpa)
|
||||
|
|
32
plugins/qpa/CMakeLists.txt
Normal file
32
plugins/qpa/CMakeLists.txt
Normal file
|
@ -0,0 +1,32 @@
|
|||
include_directories(${Qt5Core_PRIVATE_INCLUDE_DIRS})
|
||||
include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS})
|
||||
add_definitions(-DQ_FONTCONFIGDATABASE)
|
||||
|
||||
set(QPA_SOURCES
|
||||
abstractplatformcontext.cpp
|
||||
backingstore.cpp
|
||||
integration.cpp
|
||||
main.cpp
|
||||
nativeinterface.cpp
|
||||
platformcontextwayland.cpp
|
||||
screen.cpp
|
||||
sharingplatformcontext.cpp
|
||||
window.cpp
|
||||
)
|
||||
|
||||
add_library(KWinQpaPlugin MODULE ${QPA_SOURCES})
|
||||
target_link_libraries(KWinQpaPlugin
|
||||
kwin
|
||||
KF5::WaylandClient
|
||||
Wayland::Egl
|
||||
Qt5PlatformSupport::Qt5PlatformSupport
|
||||
${FONTCONFIG_LIBRARIES}
|
||||
${FREETYPE_LIBRARIES}
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
KWinQpaPlugin
|
||||
DESTINATION
|
||||
${PLUGIN_INSTALL_DIR}/platforms/
|
||||
)
|
186
plugins/qpa/abstractplatformcontext.cpp
Normal file
186
plugins/qpa/abstractplatformcontext.cpp
Normal file
|
@ -0,0 +1,186 @@
|
|||
/********************************************************************
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#include "abstractplatformcontext.h"
|
||||
#include "integration.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
namespace QPA
|
||||
{
|
||||
|
||||
static EGLConfig configFromGLFormat(EGLDisplay dpy, const QSurfaceFormat &format)
|
||||
{
|
||||
#define SIZE( __buffer__ ) format.__buffer__##BufferSize() > 0 ? format.__buffer__##BufferSize() : 0
|
||||
// not setting samples as QtQuick doesn't need it
|
||||
const EGLint config_attribs[] = {
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_RED_SIZE, SIZE(red),
|
||||
EGL_GREEN_SIZE, SIZE(green),
|
||||
EGL_BLUE_SIZE, SIZE(blue),
|
||||
EGL_ALPHA_SIZE, SIZE(alpha),
|
||||
EGL_DEPTH_SIZE, SIZE(depth),
|
||||
EGL_STENCIL_SIZE, SIZE(stencil),
|
||||
#ifdef KWIN_HAVE_OPENGLES
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
#else
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
|
||||
#endif
|
||||
EGL_NONE,
|
||||
};
|
||||
#undef SIZE
|
||||
|
||||
EGLint count;
|
||||
EGLConfig configs[1024];
|
||||
if (eglChooseConfig(dpy, config_attribs, configs, 1, &count) == EGL_FALSE) {
|
||||
return 0;
|
||||
}
|
||||
if (count != 1) {
|
||||
return 0;
|
||||
}
|
||||
return configs[0];
|
||||
}
|
||||
|
||||
static QSurfaceFormat formatFromConfig(EGLDisplay dpy, EGLConfig config)
|
||||
{
|
||||
QSurfaceFormat format;
|
||||
EGLint value = 0;
|
||||
#define HELPER(__egl__, __qt__) \
|
||||
eglGetConfigAttrib(dpy, config, EGL_##__egl__, &value); \
|
||||
format.set##__qt__(value); \
|
||||
value = 0;
|
||||
|
||||
#define BUFFER_HELPER(__eglColor__, __color__) \
|
||||
HELPER(__eglColor__##_SIZE, __color__##BufferSize)
|
||||
|
||||
BUFFER_HELPER(RED, Red)
|
||||
BUFFER_HELPER(GREEN, Green)
|
||||
BUFFER_HELPER(BLUE, Blue)
|
||||
BUFFER_HELPER(ALPHA, Alpha)
|
||||
BUFFER_HELPER(STENCIL, Stencil)
|
||||
BUFFER_HELPER(DEPTH, Depth)
|
||||
#undef BUFFER_HELPER
|
||||
HELPER(SAMPLES, Samples)
|
||||
#undef HELPER
|
||||
#ifdef KWIN_HAVE_OPENGLES
|
||||
format.setRenderableType(QSurfaceFormat::OpenGLES);
|
||||
#else
|
||||
format.setRenderableType(QSurfaceFormat::OpenGL);
|
||||
#endif
|
||||
format.setStereo(false);
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
AbstractPlatformContext::AbstractPlatformContext(QOpenGLContext *context, Integration *integration, EGLDisplay display)
|
||||
: QPlatformOpenGLContext()
|
||||
, m_integration(integration)
|
||||
, m_eglDisplay(display)
|
||||
, m_config(configFromGLFormat(m_eglDisplay, context->format()))
|
||||
, m_format(formatFromConfig(m_eglDisplay, m_config))
|
||||
{
|
||||
}
|
||||
|
||||
AbstractPlatformContext::~AbstractPlatformContext()
|
||||
{
|
||||
if (m_context != EGL_NO_CONTEXT) {
|
||||
eglDestroyContext(m_eglDisplay, m_context);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractPlatformContext::doneCurrent()
|
||||
{
|
||||
eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
QSurfaceFormat AbstractPlatformContext::format() const
|
||||
{
|
||||
return m_format;
|
||||
}
|
||||
|
||||
QFunctionPointer AbstractPlatformContext::getProcAddress(const QByteArray &procName)
|
||||
{
|
||||
return eglGetProcAddress(procName.constData());
|
||||
}
|
||||
|
||||
bool AbstractPlatformContext::isValid() const
|
||||
{
|
||||
return m_context != EGL_NO_CONTEXT;
|
||||
}
|
||||
|
||||
bool AbstractPlatformContext::bindApi()
|
||||
{
|
||||
#ifdef KWIN_HAVE_OPENGLES
|
||||
if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) {
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if (eglBindAPI(EGL_OPENGL_API) == EGL_FALSE) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void AbstractPlatformContext::createContext(EGLContext shareContext)
|
||||
{
|
||||
EGLContext context = EGL_NO_CONTEXT;
|
||||
#ifdef KWIN_HAVE_OPENGLES
|
||||
const EGLint context_attribs[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
context = eglCreateContext(eglDisplay(), config(), shareContext, context_attribs);
|
||||
#else
|
||||
const EGLint context_attribs_31_core[] = {
|
||||
EGL_CONTEXT_MAJOR_VERSION_KHR, m_format.majorVersion(),
|
||||
EGL_CONTEXT_MINOR_VERSION_KHR, m_format.minorVersion(),
|
||||
EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR,
|
||||
EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, m_format.profile() == QSurfaceFormat::CoreProfile ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR : EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
const EGLint context_attribs_legacy[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
const char* eglExtensionsCString = eglQueryString(eglDisplay(), EGL_EXTENSIONS);
|
||||
const QList<QByteArray> extensions = QByteArray::fromRawData(eglExtensionsCString, qstrlen(eglExtensionsCString)).split(' ');
|
||||
|
||||
// Try to create a 3.1 core context
|
||||
if (m_format.majorVersion() >= 3 && extensions.contains(QByteArrayLiteral("EGL_KHR_create_context"))) {
|
||||
context = eglCreateContext(eglDisplay(), config(), shareContext, context_attribs_31_core);
|
||||
}
|
||||
|
||||
if (context == EGL_NO_CONTEXT) {
|
||||
context = eglCreateContext(eglDisplay(), config(), shareContext, context_attribs_legacy);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (context == EGL_NO_CONTEXT) {
|
||||
return;
|
||||
}
|
||||
m_context = context;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
68
plugins/qpa/abstractplatformcontext.h
Normal file
68
plugins/qpa/abstractplatformcontext.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/********************************************************************
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#ifndef KWIN_QPA_ABSTRACTPLATFORMCONTEXT_H
|
||||
#define KWIN_QPA_ABSTRACTPLATFORMCONTEXT_H
|
||||
|
||||
#include <epoxy/egl.h>
|
||||
#include <fixx11h.h>
|
||||
#include <qpa/qplatformopenglcontext.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
namespace QPA
|
||||
{
|
||||
class Integration;
|
||||
|
||||
class AbstractPlatformContext : public QPlatformOpenGLContext
|
||||
{
|
||||
public:
|
||||
explicit AbstractPlatformContext(QOpenGLContext *context, Integration *integration, EGLDisplay display);
|
||||
virtual ~AbstractPlatformContext();
|
||||
|
||||
void doneCurrent() override;
|
||||
QSurfaceFormat format() const override;
|
||||
bool isValid() const override;
|
||||
QFunctionPointer getProcAddress(const QByteArray &procName) override;
|
||||
|
||||
protected:
|
||||
EGLDisplay eglDisplay() const {
|
||||
return m_eglDisplay;
|
||||
}
|
||||
EGLConfig config() const {
|
||||
return m_config;
|
||||
}
|
||||
bool bindApi();
|
||||
EGLContext context() const {
|
||||
return m_context;
|
||||
}
|
||||
void createContext(EGLContext shareContext = EGL_NO_CONTEXT);
|
||||
|
||||
private:
|
||||
Integration *m_integration;
|
||||
EGLDisplay m_eglDisplay;
|
||||
EGLConfig m_config;
|
||||
EGLContext m_context = EGL_NO_CONTEXT;
|
||||
QSurfaceFormat m_format;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
116
plugins/qpa/backingstore.cpp
Normal file
116
plugins/qpa/backingstore.cpp
Normal file
|
@ -0,0 +1,116 @@
|
|||
/********************************************************************
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#include "window.h"
|
||||
#include "backingstore.h"
|
||||
#include "../../wayland_server.h"
|
||||
|
||||
#include <KWayland/Client/connection_thread.h>
|
||||
#include <KWayland/Client/buffer.h>
|
||||
#include <KWayland/Client/shm_pool.h>
|
||||
#include <KWayland/Client/surface.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
namespace QPA
|
||||
{
|
||||
|
||||
BackingStore::BackingStore(QWindow *w, KWayland::Client::ShmPool *shm)
|
||||
: QPlatformBackingStore(w)
|
||||
, m_shm(shm)
|
||||
, m_backBuffer(QSize(), QImage::Format_ARGB32_Premultiplied)
|
||||
{
|
||||
QObject::connect(m_shm, &KWayland::Client::ShmPool::poolResized,
|
||||
[this] {
|
||||
if (!m_buffer) {
|
||||
return;
|
||||
}
|
||||
auto b = m_buffer.toStrongRef();
|
||||
if (!b->isUsed()){
|
||||
return;
|
||||
}
|
||||
const QSize size = m_backBuffer.size();
|
||||
m_backBuffer = QImage(b->address(), size.width(), size.height(), QImage::Format_ARGB32_Premultiplied);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
BackingStore::~BackingStore() = default;
|
||||
|
||||
QPaintDevice *BackingStore::paintDevice()
|
||||
{
|
||||
return &m_backBuffer;
|
||||
}
|
||||
|
||||
void BackingStore::resize(const QSize &size, const QRegion &staticContents)
|
||||
{
|
||||
Q_UNUSED(staticContents)
|
||||
m_size = size;
|
||||
if (!m_buffer) {
|
||||
return;
|
||||
}
|
||||
m_buffer.toStrongRef()->setUsed(false);
|
||||
m_buffer.clear();
|
||||
}
|
||||
|
||||
void BackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset)
|
||||
{
|
||||
Q_UNUSED(region)
|
||||
Q_UNUSED(offset)
|
||||
auto s = static_cast<Window *>(window->handle())->surface();
|
||||
s->attachBuffer(m_buffer);
|
||||
// TODO: proper damage region
|
||||
s->damage(QRect(QPoint(0, 0), m_backBuffer.size()));
|
||||
s->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
waylandServer()->internalClientConection()->flush();
|
||||
waylandServer()->dispatch();
|
||||
}
|
||||
|
||||
void BackingStore::beginPaint(const QRegion&)
|
||||
{
|
||||
if (m_buffer) {
|
||||
auto b = m_buffer.toStrongRef();
|
||||
if (b->isReleased()) {
|
||||
// we can re-use this buffer
|
||||
b->setReleased(false);
|
||||
return;
|
||||
} else {
|
||||
// buffer is still in use, get a new one
|
||||
b->setUsed(false);
|
||||
}
|
||||
}
|
||||
auto oldBuffer = m_buffer.toStrongRef();
|
||||
m_buffer.clear();
|
||||
m_buffer = m_shm->getBuffer(m_size, m_size.width() * 4);
|
||||
if (!m_buffer) {
|
||||
m_backBuffer = QImage();
|
||||
return;
|
||||
}
|
||||
auto b = m_buffer.toStrongRef();
|
||||
b->setUsed(true);
|
||||
m_backBuffer = QImage(b->address(), m_size.width(), m_size.height(), QImage::Format_ARGB32_Premultiplied);
|
||||
if (oldBuffer) {
|
||||
b->copy(oldBuffer->address());
|
||||
} else {
|
||||
m_backBuffer.fill(Qt::transparent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
60
plugins/qpa/backingstore.h
Normal file
60
plugins/qpa/backingstore.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/********************************************************************
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#ifndef KWIN_QPA_BACKINGSTORE_H
|
||||
#define KWIN_QPA_BACKINGSTORE_H
|
||||
|
||||
#include <qpa/qplatformbackingstore.h>
|
||||
|
||||
namespace KWayland
|
||||
{
|
||||
namespace Client
|
||||
{
|
||||
class Buffer;
|
||||
class ShmPool;
|
||||
}
|
||||
}
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
namespace QPA
|
||||
{
|
||||
|
||||
class BackingStore : public QPlatformBackingStore
|
||||
{
|
||||
public:
|
||||
explicit BackingStore(QWindow *w, KWayland::Client::ShmPool *shm);
|
||||
virtual ~BackingStore();
|
||||
|
||||
QPaintDevice *paintDevice() override;
|
||||
void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) override;
|
||||
void resize(const QSize &size, const QRegion &staticContents) override;
|
||||
void beginPaint(const QRegion &) override;
|
||||
|
||||
private:
|
||||
KWayland::Client::ShmPool *m_shm;
|
||||
QWeakPointer<KWayland::Client::Buffer> m_buffer;
|
||||
QImage m_backBuffer;
|
||||
QSize m_size;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
256
plugins/qpa/integration.cpp
Normal file
256
plugins/qpa/integration.cpp
Normal file
|
@ -0,0 +1,256 @@
|
|||
/********************************************************************
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#define WL_EGL_PLATFORM 1
|
||||
#include "integration.h"
|
||||
#include "abstract_backend.h"
|
||||
#include "backingstore.h"
|
||||
#include "nativeinterface.h"
|
||||
#include "platformcontextwayland.h"
|
||||
#include "screen.h"
|
||||
#include "sharingplatformcontext.h"
|
||||
#include "window.h"
|
||||
#include "../../main.h"
|
||||
#include "../../wayland_server.h"
|
||||
|
||||
#include <KWayland/Client/compositor.h>
|
||||
#include <KWayland/Client/connection_thread.h>
|
||||
#include <KWayland/Client/output.h>
|
||||
#include <KWayland/Client/registry.h>
|
||||
#include <KWayland/Client/shell.h>
|
||||
#include <KWayland/Server/clientconnection.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QtConcurrentRun>
|
||||
|
||||
#include <qpa/qplatformwindow.h>
|
||||
#include <QtCore/private/qeventdispatcher_unix_p.h>
|
||||
#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
|
||||
#include <QtPlatformSupport/private/qgenericunixthemes_p.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
namespace QPA
|
||||
{
|
||||
|
||||
Integration::Integration()
|
||||
: QObject()
|
||||
, QPlatformIntegration()
|
||||
, m_fontDb(new QGenericUnixFontDatabase())
|
||||
, m_nativeInterface(new NativeInterface(this))
|
||||
{
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
// TODO: start initialize Wayland once the internal Wayland connection is created
|
||||
connect(kwinApp(), &Application::screensCreated, this, &Integration::initializeWayland, Qt::QueuedConnection);
|
||||
QPlatformIntegration::initialize();
|
||||
}
|
||||
|
||||
QAbstractEventDispatcher *Integration::createEventDispatcher() const
|
||||
{
|
||||
// TODO: add our own event dispatcher
|
||||
return new QEventDispatcherUNIX;
|
||||
}
|
||||
|
||||
QPlatformBackingStore *Integration::createPlatformBackingStore(QWindow *window) const
|
||||
{
|
||||
auto registry = waylandServer()->internalClientRegistry();
|
||||
const auto shm = registry->interface(KWayland::Client::Registry::Interface::Shm);
|
||||
if (shm.name == 0u) {
|
||||
return nullptr;
|
||||
}
|
||||
return new BackingStore(window, registry->createShmPool(shm.name, shm.version, window));
|
||||
}
|
||||
|
||||
QPlatformWindow *Integration::createPlatformWindow(QWindow *window) const
|
||||
{
|
||||
auto c = compositor();
|
||||
auto s = shell();
|
||||
if (!s || !c) {
|
||||
return new QPlatformWindow(window);
|
||||
} else {
|
||||
// don't set window as parent, cause infinite recursion in PlasmaQuick::Dialog
|
||||
auto surface = c->createSurface();
|
||||
return new Window(window, surface, s->createSurface(surface), this);
|
||||
}
|
||||
}
|
||||
|
||||
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)});
|
||||
}
|
||||
|
||||
QPlatformNativeInterface *Integration::nativeInterface() const
|
||||
{
|
||||
return m_nativeInterface;
|
||||
}
|
||||
|
||||
QPlatformOpenGLContext *Integration::createPlatformOpenGLContext(QOpenGLContext *context) const
|
||||
{
|
||||
if (waylandServer()->backend()->supportsQpaContext()) {
|
||||
return new SharingPlatformContext(context, const_cast<Integration*>(this));
|
||||
}
|
||||
if (m_eglDisplay == EGL_NO_DISPLAY) {
|
||||
const_cast<Integration*>(this)->initEgl();
|
||||
}
|
||||
if (m_eglDisplay == EGL_NO_DISPLAY) {
|
||||
return nullptr;
|
||||
}
|
||||
return new PlatformContextWayland(context, const_cast<Integration*>(this));
|
||||
}
|
||||
|
||||
void Integration::initializeWayland()
|
||||
{
|
||||
if (m_registry) {
|
||||
return;
|
||||
}
|
||||
using namespace KWayland::Client;
|
||||
auto setupRegistry = [this] {
|
||||
m_registry = waylandServer()->internalClientRegistry();
|
||||
connect(m_registry, &Registry::outputAnnounced, this, &Integration::createWaylandOutput);
|
||||
const auto outputs = m_registry->interfaces(Registry::Interface::Output);
|
||||
for (const auto &o : outputs) {
|
||||
createWaylandOutput(o.name, o.version);
|
||||
}
|
||||
};
|
||||
if (waylandServer()->internalClientRegistry()) {
|
||||
setupRegistry();
|
||||
} else {
|
||||
connect(waylandServer()->internalClientConection(), &ConnectionThread::connected, this, setupRegistry, Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
|
||||
void Integration::createWaylandOutput(quint32 name, quint32 version)
|
||||
{
|
||||
using namespace KWayland::Client;
|
||||
auto o = m_registry->createOutput(name, version, this);
|
||||
connect(o, &Output::changed, this,
|
||||
[this, o] {
|
||||
disconnect(o, &Output::changed, nullptr, nullptr);
|
||||
// TODO: handle screen removal
|
||||
screenAdded(new Screen(o));
|
||||
}
|
||||
);
|
||||
waylandServer()->internalClientConection()->flush();
|
||||
}
|
||||
|
||||
KWayland::Client::Compositor *Integration::compositor() const
|
||||
{
|
||||
if (!m_compositor) {
|
||||
using namespace KWayland::Client;
|
||||
auto registry = waylandServer()->internalClientRegistry();
|
||||
const auto c = registry->interface(Registry::Interface::Compositor);
|
||||
if (c.name != 0u) {
|
||||
const_cast<Integration*>(this)->m_compositor = registry->createCompositor(c.name, c.version);
|
||||
}
|
||||
}
|
||||
return m_compositor;
|
||||
}
|
||||
|
||||
KWayland::Client::Shell *Integration::shell() const
|
||||
{
|
||||
if (!m_shell) {
|
||||
using namespace KWayland::Client;
|
||||
auto registry = waylandServer()->internalClientRegistry();
|
||||
const auto s = registry->interface(Registry::Interface::Shell);
|
||||
if (s.name != 0u) {
|
||||
const_cast<Integration*>(this)->m_shell = registry->createShell(s.name, s.version);
|
||||
}
|
||||
}
|
||||
return m_shell;
|
||||
}
|
||||
|
||||
EGLDisplay Integration::eglDisplay() const
|
||||
{
|
||||
return m_eglDisplay;
|
||||
}
|
||||
|
||||
void Integration::initEgl()
|
||||
{
|
||||
Q_ASSERT(m_eglDisplay == EGL_NO_DISPLAY);
|
||||
// This variant uses Wayland as the EGL platform
|
||||
qputenv("EGL_PLATFORM", "wayland");
|
||||
m_eglDisplay = eglGetDisplay(waylandServer()->internalClientConection()->display());
|
||||
if (m_eglDisplay == EGL_NO_DISPLAY) {
|
||||
return;
|
||||
}
|
||||
// call eglInitialize in a thread to not block
|
||||
QFuture<bool> future = QtConcurrent::run([this] () -> bool {
|
||||
EGLint major, minor;
|
||||
if (eglInitialize(m_eglDisplay, &major, &minor) == EGL_FALSE) {
|
||||
return false;
|
||||
}
|
||||
EGLint error = eglGetError();
|
||||
if (error != EGL_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
// TODO: make this better
|
||||
while (!future.isFinished()) {
|
||||
waylandServer()->internalClientConection()->flush();
|
||||
QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
|
||||
}
|
||||
if (!future.result()) {
|
||||
eglTerminate(m_eglDisplay);
|
||||
m_eglDisplay = EGL_NO_DISPLAY;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
82
plugins/qpa/integration.h
Normal file
82
plugins/qpa/integration.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
/********************************************************************
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#ifndef KWIN_QPA_INTEGRATION_H
|
||||
#define KWIN_QPA_INTEGRATION_H
|
||||
|
||||
#include <epoxy/egl.h>
|
||||
#include <fixx11h.h>
|
||||
#include <qpa/qplatformintegration.h>
|
||||
#include <QObject>
|
||||
|
||||
namespace KWayland
|
||||
{
|
||||
namespace Client
|
||||
{
|
||||
class Registry;
|
||||
class Compositor;
|
||||
class Shell;
|
||||
}
|
||||
}
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
namespace QPA
|
||||
{
|
||||
|
||||
class Integration : public QObject, public QPlatformIntegration
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Integration();
|
||||
virtual ~Integration();
|
||||
|
||||
bool hasCapability(Capability cap) const override;
|
||||
QPlatformWindow *createPlatformWindow(QWindow *window) const override;
|
||||
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
|
||||
QAbstractEventDispatcher *createEventDispatcher() const override;
|
||||
QPlatformFontDatabase *fontDatabase() const override;
|
||||
QStringList themeNames() const override;
|
||||
QPlatformTheme *createPlatformTheme(const QString &name) const override;
|
||||
QPlatformNativeInterface *nativeInterface() const override;
|
||||
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override;
|
||||
|
||||
void initialize() override;
|
||||
|
||||
KWayland::Client::Compositor *compositor() const;
|
||||
EGLDisplay eglDisplay() const;
|
||||
|
||||
private:
|
||||
void initializeWayland();
|
||||
void createWaylandOutput(quint32 name, quint32 version);
|
||||
void initEgl();
|
||||
KWayland::Client::Shell *shell() const;
|
||||
|
||||
QPlatformFontDatabase *m_fontDb;
|
||||
QPlatformNativeInterface *m_nativeInterface;
|
||||
KWayland::Client::Registry *m_registry = nullptr;
|
||||
KWayland::Client::Compositor *m_compositor = nullptr;
|
||||
KWayland::Client::Shell *m_shell = nullptr;
|
||||
EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
3
plugins/qpa/kwin.json
Normal file
3
plugins/qpa/kwin.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"Keys": [ "wayland-org.kde.kwin.qpa" ]
|
||||
}
|
47
plugins/qpa/main.cpp
Normal file
47
plugins/qpa/main.cpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
/********************************************************************
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#include "integration.h"
|
||||
#include <qpa/qplatformintegrationplugin.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
class KWinIntegrationPlugin : public QPlatformIntegrationPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "kwin.json")
|
||||
public:
|
||||
QPlatformIntegration *create(const QString &system, const QStringList ¶mList) override;
|
||||
};
|
||||
|
||||
QPlatformIntegration *KWinIntegrationPlugin::create(const QString &system, const QStringList ¶mList)
|
||||
{
|
||||
Q_UNUSED(paramList)
|
||||
if (!QCoreApplication::applicationFilePath().endsWith(QLatin1Literal("kwin_wayland"))) {
|
||||
// Not KWin
|
||||
return nullptr;
|
||||
}
|
||||
if (system.compare(QLatin1String("wayland-org.kde.kwin.qpa"), Qt::CaseInsensitive) == 0) {
|
||||
// create our integration
|
||||
return new KWin::QPA::Integration;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#include "main.moc"
|
77
plugins/qpa/nativeinterface.cpp
Normal file
77
plugins/qpa/nativeinterface.cpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
/********************************************************************
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#include "nativeinterface.h"
|
||||
#include "integration.h"
|
||||
#include "window.h"
|
||||
#include "../../wayland_server.h"
|
||||
|
||||
#include <QWindow>
|
||||
|
||||
#include <KWayland/Client/connection_thread.h>
|
||||
#include <KWayland/Client/compositor.h>
|
||||
#include <KWayland/Client/surface.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
namespace QPA
|
||||
{
|
||||
|
||||
static const QByteArray s_displayKey = QByteArrayLiteral("display");
|
||||
static const QByteArray s_wlDisplayKey = QByteArrayLiteral("wl_display");
|
||||
static const QByteArray s_compositorKey = QByteArrayLiteral("compositor");
|
||||
static const QByteArray s_surfaceKey = QByteArrayLiteral("surface");
|
||||
|
||||
NativeInterface::NativeInterface(Integration *integration)
|
||||
: QPlatformNativeInterface()
|
||||
, m_integration(integration)
|
||||
{
|
||||
}
|
||||
|
||||
void *NativeInterface::nativeResourceForIntegration(const QByteArray &resource)
|
||||
{
|
||||
const QByteArray r = resource.toLower();
|
||||
if (r == s_displayKey || r == s_wlDisplayKey) {
|
||||
return waylandServer()->internalClientConection()->display();
|
||||
}
|
||||
if (r == s_compositorKey) {
|
||||
return static_cast<wl_compositor*>(*m_integration->compositor());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void *NativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
|
||||
{
|
||||
const QByteArray r = resource.toLower();
|
||||
if (r == s_displayKey || r == s_wlDisplayKey) {
|
||||
return waylandServer()->internalClientConection()->display();
|
||||
}
|
||||
if (r == s_compositorKey) {
|
||||
return static_cast<wl_compositor*>(*m_integration->compositor());
|
||||
}
|
||||
if (r == s_surfaceKey && window) {
|
||||
if (auto handle = window->handle()) {
|
||||
return static_cast<wl_surface*>(*static_cast<Window*>(handle)->surface());
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
46
plugins/qpa/nativeinterface.h
Normal file
46
plugins/qpa/nativeinterface.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/********************************************************************
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#ifndef KWIN_QPA_NATIVEINTERFACE_H
|
||||
#define KWIN_QPA_NATIVEINTERFACE_H
|
||||
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
namespace QPA
|
||||
{
|
||||
|
||||
class Integration;
|
||||
|
||||
class NativeInterface : public QPlatformNativeInterface
|
||||
{
|
||||
public:
|
||||
explicit NativeInterface(Integration *integration);
|
||||
void *nativeResourceForIntegration(const QByteArray &resource) override;
|
||||
void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) override;
|
||||
|
||||
private:
|
||||
Integration *m_integration;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
77
plugins/qpa/platformcontextwayland.cpp
Normal file
77
plugins/qpa/platformcontextwayland.cpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
/********************************************************************
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#include "platformcontextwayland.h"
|
||||
#include "integration.h"
|
||||
#include "window.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
namespace QPA
|
||||
{
|
||||
|
||||
PlatformContextWayland::PlatformContextWayland(QOpenGLContext *context, Integration *integration)
|
||||
: AbstractPlatformContext(context, integration, integration->eglDisplay())
|
||||
{
|
||||
create();
|
||||
}
|
||||
|
||||
bool PlatformContextWayland::makeCurrent(QPlatformSurface *surface)
|
||||
{
|
||||
Window *window = static_cast<Window*>(surface);
|
||||
EGLSurface s = window->eglSurface();
|
||||
if (s == EGL_NO_SURFACE) {
|
||||
window->createEglSurface(eglDisplay(), config());
|
||||
s = window->eglSurface();
|
||||
if (s == EGL_NO_SURFACE) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return eglMakeCurrent(eglDisplay(), s, s, context());
|
||||
}
|
||||
|
||||
bool PlatformContextWayland::isSharing() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void PlatformContextWayland::swapBuffers(QPlatformSurface *surface)
|
||||
{
|
||||
Window *window = static_cast<Window*>(surface);
|
||||
EGLSurface s = window->eglSurface();
|
||||
if (s == EGL_NO_SURFACE) {
|
||||
return;
|
||||
}
|
||||
eglSwapBuffers(eglDisplay(), s);
|
||||
}
|
||||
|
||||
void PlatformContextWayland::create()
|
||||
{
|
||||
if (config() == 0) {
|
||||
return;
|
||||
}
|
||||
if (!bindApi()) {
|
||||
return;
|
||||
}
|
||||
createContext();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
49
plugins/qpa/platformcontextwayland.h
Normal file
49
plugins/qpa/platformcontextwayland.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/********************************************************************
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#ifndef KWIN_QPA_PLATFORMCONTEXTWAYLAND_H
|
||||
#define KWIN_QPA_PLATFORMCONTEXTWAYLAND_H
|
||||
|
||||
#include "abstractplatformcontext.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
namespace QPA
|
||||
{
|
||||
class Integration;
|
||||
|
||||
class PlatformContextWayland : public AbstractPlatformContext
|
||||
{
|
||||
public:
|
||||
explicit PlatformContextWayland(QOpenGLContext *context, Integration *integration);
|
||||
|
||||
void swapBuffers(QPlatformSurface *surface) override;
|
||||
|
||||
bool makeCurrent(QPlatformSurface *surface) override;
|
||||
|
||||
bool isSharing() const override;
|
||||
|
||||
private:
|
||||
void create();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
59
plugins/qpa/screen.cpp
Normal file
59
plugins/qpa/screen.cpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
/********************************************************************
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#include "screen.h"
|
||||
|
||||
#include <KWayland/Client/output.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
namespace QPA
|
||||
{
|
||||
|
||||
Screen::Screen(KWayland::Client::Output *o)
|
||||
: QPlatformScreen()
|
||||
, m_output(o)
|
||||
{
|
||||
// TODO: connect to resolution changes
|
||||
}
|
||||
|
||||
Screen::~Screen() = default;
|
||||
|
||||
int Screen::depth() const
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
|
||||
QImage::Format Screen::format() const
|
||||
{
|
||||
return QImage::Format_ARGB32_Premultiplied;
|
||||
}
|
||||
|
||||
QRect Screen::geometry() const
|
||||
{
|
||||
return m_output->geometry();
|
||||
}
|
||||
|
||||
QSizeF Screen::physicalSize() const
|
||||
{
|
||||
return m_output->physicalSize();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
56
plugins/qpa/screen.h
Normal file
56
plugins/qpa/screen.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/********************************************************************
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#ifndef KWIN_QPA_SCREEN_H
|
||||
#define KWIN_QPA_SCREEN_H
|
||||
|
||||
#include <qpa/qplatformscreen.h>
|
||||
|
||||
namespace KWayland
|
||||
{
|
||||
namespace Client
|
||||
{
|
||||
class Output;
|
||||
}
|
||||
}
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
namespace QPA
|
||||
{
|
||||
|
||||
class Screen : public QPlatformScreen
|
||||
{
|
||||
public:
|
||||
explicit Screen(KWayland::Client::Output *o);
|
||||
virtual ~Screen();
|
||||
|
||||
QRect geometry() const override;
|
||||
int depth() const override;
|
||||
QImage::Format format() const override;
|
||||
QSizeF physicalSize() const override;
|
||||
|
||||
private:
|
||||
KWayland::Client::Output *m_output;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
92
plugins/qpa/sharingplatformcontext.cpp
Normal file
92
plugins/qpa/sharingplatformcontext.cpp
Normal file
|
@ -0,0 +1,92 @@
|
|||
/********************************************************************
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#include "sharingplatformcontext.h"
|
||||
#include "integration.h"
|
||||
#include "window.h"
|
||||
#include "../../abstract_backend.h"
|
||||
#include "../../wayland_server.h"
|
||||
#include "../../shell_client.h"
|
||||
|
||||
#include <QOpenGLFramebufferObject>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
namespace QPA
|
||||
{
|
||||
|
||||
SharingPlatformContext::SharingPlatformContext(QOpenGLContext *context, Integration *integration)
|
||||
: AbstractPlatformContext(context, integration, waylandServer()->backend()->sceneEglDisplay())
|
||||
{
|
||||
create();
|
||||
}
|
||||
|
||||
bool SharingPlatformContext::makeCurrent(QPlatformSurface *surface)
|
||||
{
|
||||
Window *window = static_cast<Window*>(surface);
|
||||
if (eglMakeCurrent(eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, context())) {
|
||||
window->bindContentFBO();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SharingPlatformContext::isSharing() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void SharingPlatformContext::swapBuffers(QPlatformSurface *surface)
|
||||
{
|
||||
Window *window = static_cast<Window*>(surface);
|
||||
auto c = window->shellClient();
|
||||
if (!c) {
|
||||
return;
|
||||
}
|
||||
makeCurrent(surface);
|
||||
glFlush();
|
||||
c->setInternalFramebufferObject(window->swapFBO());
|
||||
window->bindContentFBO();
|
||||
}
|
||||
|
||||
GLuint SharingPlatformContext::defaultFramebufferObject(QPlatformSurface *surface) const
|
||||
{
|
||||
if (Window *window = dynamic_cast<Window*>(surface)) {
|
||||
const auto &fbo = window->contentFBO();
|
||||
if (!fbo.isNull()) {
|
||||
return fbo->handle();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SharingPlatformContext::create()
|
||||
{
|
||||
if (config() == 0) {
|
||||
return;
|
||||
}
|
||||
if (!bindApi()) {
|
||||
return;
|
||||
}
|
||||
createContext(waylandServer()->backend()->sceneEglContext());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
51
plugins/qpa/sharingplatformcontext.h
Normal file
51
plugins/qpa/sharingplatformcontext.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/********************************************************************
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#ifndef KWIN_QPA_SHARINGPLATFORMCONTEXT_H
|
||||
#define KWIN_QPA_SHARINGPLATFORMCONTEXT_H
|
||||
|
||||
#include "abstractplatformcontext.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
namespace QPA
|
||||
{
|
||||
class Integration;
|
||||
|
||||
class SharingPlatformContext : public AbstractPlatformContext
|
||||
{
|
||||
public:
|
||||
explicit SharingPlatformContext(QOpenGLContext *context, Integration *integration);
|
||||
|
||||
void swapBuffers(QPlatformSurface *surface) override;
|
||||
|
||||
GLuint defaultFramebufferObject(QPlatformSurface *surface) const override;
|
||||
|
||||
bool makeCurrent(QPlatformSurface *surface) override;
|
||||
|
||||
bool isSharing() const override;
|
||||
|
||||
private:
|
||||
void create();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
153
plugins/qpa/window.cpp
Normal file
153
plugins/qpa/window.cpp
Normal file
|
@ -0,0 +1,153 @@
|
|||
/********************************************************************
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#define WL_EGL_PLATFORM 1
|
||||
#include "integration.h"
|
||||
#include "window.h"
|
||||
#include "../../shell_client.h"
|
||||
#include "../../wayland_server.h"
|
||||
|
||||
#include <QOpenGLFramebufferObject>
|
||||
|
||||
#include <KWayland/Client/buffer.h>
|
||||
#include <KWayland/Client/connection_thread.h>
|
||||
#include <KWayland/Client/shell.h>
|
||||
#include <KWayland/Client/surface.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
namespace QPA
|
||||
{
|
||||
static quint32 s_windowId = 0;
|
||||
|
||||
Window::Window(QWindow *window, KWayland::Client::Surface *surface, KWayland::Client::ShellSurface *shellSurface, const Integration *integration)
|
||||
: QPlatformWindow(window)
|
||||
, m_surface(surface)
|
||||
, m_shellSurface(shellSurface)
|
||||
, m_windowId(++s_windowId)
|
||||
, m_integration(integration)
|
||||
{
|
||||
waylandServer()->internalClientConection()->flush();
|
||||
}
|
||||
|
||||
Window::~Window()
|
||||
{
|
||||
unmap();
|
||||
if (m_eglSurface != EGL_NO_SURFACE) {
|
||||
eglDestroySurface(m_integration->eglDisplay(), m_eglSurface);
|
||||
}
|
||||
if (m_eglWaylandWindow) {
|
||||
wl_egl_window_destroy(m_eglWaylandWindow);
|
||||
}
|
||||
delete m_shellSurface;
|
||||
delete m_surface;
|
||||
waylandServer()->internalClientConection()->flush();
|
||||
}
|
||||
|
||||
WId Window::winId() const
|
||||
{
|
||||
return m_windowId;
|
||||
}
|
||||
|
||||
void Window::setVisible(bool visible)
|
||||
{
|
||||
if (!visible) {
|
||||
unmap();
|
||||
}
|
||||
QPlatformWindow::setVisible(visible);
|
||||
}
|
||||
|
||||
void Window::setGeometry(const QRect &rect)
|
||||
{
|
||||
const QRect &oldRect = geometry();
|
||||
QPlatformWindow::setGeometry(rect);
|
||||
if (rect.x() != oldRect.x()) {
|
||||
emit window()->xChanged(rect.x());
|
||||
}
|
||||
if (rect.y() != oldRect.y()) {
|
||||
emit window()->yChanged(rect.y());
|
||||
}
|
||||
if (rect.width() != oldRect.width()) {
|
||||
emit window()->widthChanged(rect.width());
|
||||
}
|
||||
if (rect.height() != oldRect.height()) {
|
||||
emit window()->heightChanged(rect.height());
|
||||
}
|
||||
if (m_contentFBO) {
|
||||
if (m_contentFBO->width() != geometry().width() || m_contentFBO->height() != geometry().height()) {
|
||||
m_resized = true;
|
||||
}
|
||||
}
|
||||
if (m_eglWaylandWindow) {
|
||||
wl_egl_window_resize(m_eglWaylandWindow, geometry().width(), geometry().height(), 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::unmap()
|
||||
{
|
||||
if (m_shellClient) {
|
||||
m_shellClient->setInternalFramebufferObject(QSharedPointer<QOpenGLFramebufferObject>());
|
||||
}
|
||||
m_surface->attachBuffer(KWayland::Client::Buffer::Ptr());
|
||||
m_surface->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
waylandServer()->internalClientConection()->flush();
|
||||
}
|
||||
|
||||
void Window::createEglSurface(EGLDisplay dpy, EGLConfig config)
|
||||
{
|
||||
const QSize size = window()->size();
|
||||
m_eglWaylandWindow = wl_egl_window_create(*m_surface, size.width(), size.height());
|
||||
if (!m_eglWaylandWindow) {
|
||||
return;
|
||||
}
|
||||
m_eglSurface = eglCreateWindowSurface(dpy, config, m_eglWaylandWindow, nullptr);
|
||||
}
|
||||
|
||||
void Window::bindContentFBO()
|
||||
{
|
||||
if (m_resized || !m_contentFBO) {
|
||||
createFBO();
|
||||
}
|
||||
m_contentFBO->bind();
|
||||
}
|
||||
|
||||
QSharedPointer<QOpenGLFramebufferObject> Window::swapFBO()
|
||||
{
|
||||
auto fbo = m_contentFBO;
|
||||
m_contentFBO.clear();
|
||||
return fbo;
|
||||
}
|
||||
|
||||
void Window::createFBO()
|
||||
{
|
||||
const QRect &r = geometry();
|
||||
m_contentFBO.reset(new QOpenGLFramebufferObject(r.width(), r.height(), QOpenGLFramebufferObject::CombinedDepthStencil));
|
||||
m_resized = false;
|
||||
}
|
||||
|
||||
ShellClient *Window::shellClient()
|
||||
{
|
||||
if (!m_shellClient) {
|
||||
m_shellClient = waylandServer()->findClient(window());
|
||||
}
|
||||
return m_shellClient;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
95
plugins/qpa/window.h
Normal file
95
plugins/qpa/window.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
/********************************************************************
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#ifndef KWIN_QPA_WINDOW_H
|
||||
#define KWIN_QPA_WINDOW_H
|
||||
|
||||
#include <epoxy/egl.h>
|
||||
#include <fixx11h.h>
|
||||
#include <qpa/qplatformwindow.h>
|
||||
// wayland
|
||||
#include <wayland-egl.h>
|
||||
|
||||
class QOpenGLFramebufferObject;
|
||||
|
||||
struct wl_egl_window;
|
||||
|
||||
namespace KWayland
|
||||
{
|
||||
namespace Client
|
||||
{
|
||||
class Surface;
|
||||
class ShellSurface;
|
||||
}
|
||||
}
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class ShellClient;
|
||||
|
||||
namespace QPA
|
||||
{
|
||||
|
||||
class Integration;
|
||||
|
||||
class Window : public QPlatformWindow
|
||||
{
|
||||
public:
|
||||
explicit Window(QWindow *window, KWayland::Client::Surface *surface, KWayland::Client::ShellSurface *shellSurface, const Integration *integration);
|
||||
virtual ~Window();
|
||||
|
||||
void setVisible(bool visible) override;
|
||||
void setGeometry(const QRect &rect) override;
|
||||
WId winId() const override;
|
||||
|
||||
KWayland::Client::Surface *surface() const {
|
||||
return m_surface;
|
||||
}
|
||||
EGLSurface eglSurface() const {
|
||||
return m_eglSurface;
|
||||
}
|
||||
void createEglSurface(EGLDisplay dpy, EGLConfig config);
|
||||
|
||||
void bindContentFBO();
|
||||
const QSharedPointer<QOpenGLFramebufferObject> &contentFBO() const {
|
||||
return m_contentFBO;
|
||||
}
|
||||
QSharedPointer<QOpenGLFramebufferObject> swapFBO();
|
||||
ShellClient *shellClient();
|
||||
|
||||
private:
|
||||
void unmap();
|
||||
void createFBO();
|
||||
|
||||
KWayland::Client::Surface *m_surface;
|
||||
KWayland::Client::ShellSurface *m_shellSurface;
|
||||
EGLSurface m_eglSurface = EGL_NO_SURFACE;
|
||||
QSharedPointer<QOpenGLFramebufferObject> m_contentFBO;
|
||||
bool m_resized = false;
|
||||
ShellClient *m_shellClient = nullptr;
|
||||
wl_egl_window *m_eglWaylandWindow = nullptr;
|
||||
quint32 m_windowId;
|
||||
const Integration *m_integration;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue