Commit d1865e99 authored by Christoph Haag's avatar Christoph Haag
Browse files

bare skeleton

add license
parents
cmake_minimum_required (VERSION 3.0)
project (kwin-effects-vrdesktop)
include (FeatureSummary)
add_definitions (-Wall -Werror)
set (CMAKE_CXX_STANDARD 14)
set (CMAKE_CXX_STANDARD_REQUIRED ON)
set (CMAKE_CXX_EXTENSIONS OFF)
find_package (ECM REQUIRED NO_MODULE)
set (CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
${ECM_MODULE_PATH}
${ECM_KDE_MODULE_DIR}
${CMAKE_SOURCE_DIR}/cmake
${CMAKE_SOURCE_DIR}/cmake/Modules
)
include(KDEInstallDirs)
include(KDECMakeSettings)
add_subdirectory (src)
feature_summary (WHAT ALL)
The MIT License (MIT)
Copyright 2018 Collabora Ltd.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# VR Mirror kwin effect
Mirror desktop windows into VR
## Installation
ArchLinux: PKGBUILD etc.
## Activating the Effect and Shortcuts
First the effect has to be activated. Then in the effect settings a hotkey needs to be set.
(no default shortcut for now (TODO))
You can find it in systemsettings5, or shorter by directly opening the kwin effects kcm:
kcmshell5 kcmkwineffects
Filter by "vr mirror" to find the effect faster.
# - Try to find kwineffects
#
# Once done this will define
# KWINEFFECTS_FOUND - System has kwineffects
# KWINEFFECTS_INCLUDE_DIRS - The kwineffects include directories
# KWINEFFECTS_LIBRARIES - The libraries needed to use kwineffects
#
# Also, once done this will define the following targets
# KWinEffects::KWinEffects
#
find_path (KWINEFFECTS_INCLUDE_DIRS
NAMES kwineffects.h
)
find_library (KWINEFFECTS_LIBRARY
NAMES kwineffects
)
include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (KWinEffects DEFAULT_MSG
KWINEFFECTS_LIBRARY KWINEFFECTS_INCLUDE_DIRS
)
mark_as_advanced (KWINEFFECTS_LIBRARY)
set (KWINEFFECTS_LIBRARIES ${KWINEFFECTS_LIBRARY})
if (KWINEFFECTS_FOUND)
add_library (KWinEffects::KWinEffects UNKNOWN IMPORTED)
set_target_properties (KWinEffects::KWinEffects PROPERTIES
IMPORTED_LOCATION "${KWINEFFECTS_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${KWINEFFECTS_INCLUDE_DIRS}"
)
endif ()
#######################################
# Effect
#######################################
# Config
add_subdirectory( kcm )
find_package (Qt5 REQUIRED COMPONENTS
Core
)
find_package (KF5 REQUIRED COMPONENTS
Service
WindowSystem
GlobalAccel
I18n
)
find_package (KWinEffects REQUIRED)
set(kwin_effect_vrmirror_SRCS VRMirror.cpp)
qt5_add_resources(kwin_effect_vrmirror_SRCS)
add_library(kwin_effect_vrmirror SHARED ${kwin_effect_vrmirror_SRCS})
target_link_libraries(kwin_effect_vrmirror
PUBLIC
Qt5::Core
KF5::WindowSystem
KF5::Service
KF5::GlobalAccel
KF5::I18n
KWinEffects::KWinEffects
)
kcoreaddons_desktop_to_json(kwin_effect_vrmirror vrmirror.desktop SERVICE_TYPES kwineffect.desktop)
install(
TARGETS
kwin_effect_vrmirror
DESTINATION
${PLUGIN_INSTALL_DIR}/kwin/effects/plugins/
)
/*
* KWin XRDesktop Plugin
* Copyright 2018 Collabora Ltd.
* Author: Christoph Haag <christoph.haag@collabora.com>
* SPDX-License-Identifier: MIT
*/
#include "VRMirror.h"
#include <QAction>
#include <QFile>
#include <kwinglutils.h>
#include <kwinglplatform.h>
#include <kwindowsystem.h>
#include <QStandardPaths>
#include <QAction>
#include <KGlobalAccel>
#include <KLocalizedString>
#include <QMatrix4x4>
#include <QtDebug>
KWIN_EFFECT_FACTORY_SUPPORTED_ENABLED(VRMirrorFactory,
VRMirror,
"vrmirror.json",
return VRMirror::supported();,
return VRMirror::enabledByDefault();)
VRMirror::VRMirror()
: m_vrmirrorRunning(false)
{
auto *toggleAction = new QAction(this);
toggleAction->setObjectName(QStringLiteral("Toggle"));
toggleAction->setText(i18n("Toggle VR Desktop"));
KGlobalAccel::self()->setDefaultShortcut(toggleAction, {});
KGlobalAccel::self()->setShortcut(toggleAction, {});
KWin::effects->registerGlobalShortcut({}, toggleAction);
connect(toggleAction, &QAction::triggered, this, &VRMirror::toggleScreenVRMirror);
connect(KWin::effects, SIGNAL(windowClosed(KWin::EffectWindow*)), this, SLOT(slotWindowClosed(KWin::EffectWindow*)));
connect(KWin::effects, &KWin::EffectsHandler::windowClosed, this, &VRMirror::slotWindowClosed);
connect(KWin::effects, &KWin::EffectsHandler::windowAdded, this, &VRMirror::slotWindowAdded);
}
VRMirror::~VRMirror()
{
}
bool VRMirror::supported()
{
return KWin::effects->compositingType() == KWin::OpenGL2Compositing;
}
bool VRMirror::enabledByDefault()
{
return supported();
}
bool VRMirror::initVR()
{
// TODO: init openvr-glib
return true;
}
void VRMirror::prePaintScreen(KWin::ScreenPrePaintData &data, int time)
{
KWin::effects->prePaintScreen(data, time);
}
void VRMirror::prePaintWindow(KWin::EffectWindow *w, KWin::WindowPrePaintData &data, int time)
{
if (m_vrmirrorRunning && isMirrored(w)) {
data.mask |= PAINT_WINDOW_TRANSFORMED;
}
KWin::effects->prePaintWindow(w, data, time);
}
void VRMirror::drawWindow(KWin::EffectWindow* w, int mask, QRegion region, KWin::WindowPaintData& data)
{
if (m_vrmirrorRunning && isMirrored(w)) {
qDebug() << "draw window " << w->caption();
}
KWin::effects->drawWindow(w, mask, region, data);
}
void VRMirror::paintWindow(KWin::EffectWindow* w, int mask, QRegion region, KWin::WindowPaintData& data)
{
if (m_vrmirrorRunning && isMirrored(w)) {
//qDebug() << "paint window " << w->caption();
}
KWin::effects->paintWindow(w, mask, region, data);
}
void VRMirror::paintEffectFrame(KWin::EffectFrame* frame, QRegion region, double opacity, double frameOpacity)
{
if (m_vrmirrorRunning) {
qDebug() << "painteffectframe";
}
KWin::effects->paintEffectFrame(frame, region, opacity, frameOpacity);
}
void VRMirror::slotWindowClosed(KWin::EffectWindow* w)
{
if (!m_vrmirrorRunning)
return;
qDebug() << "Window closed: " << w->caption();
VRWindow *win = removeMirrored(w);
if (win)
delete (win);
}
void VRMirror::slotWindowAdded(KWin::EffectWindow* w)
{
if (!m_vrmirrorRunning)
return;
qDebug() << "Window added: " << w->caption();
m_mirroredWindows.append(new VRWindow(w));
}
void VRMirror::toggleScreenVRMirror()
{
if (m_vrmirrorRunning) {
qDebug() << "deactivating VR mirror...";
m_vrmirrorRunning = false;
clear_mirrored();
return;
}
qDebug() << "activating VR mirror...";
if (!m_vrmirrorInitialized)
m_vrmirrorInitialized = initVR();
// if for some reason we couldn't initialize the vr mirror, don't start it
if (!m_vrmirrorInitialized)
return;
for (int i = 0; i < KWindowSystem::windows().count(); ++i) {
if (KWin::EffectWindow *win = KWin::effects->findWindow(KWindowSystem::windows().at(i))) {
m_mirroredWindows.append(new VRWindow(win));
qDebug() << "Adding window " << win->caption();
}
}
m_vrmirrorRunning = true;
qDebug() << "VR Mirror activated";
KWin::effects->addRepaintFull();
}
bool VRMirror::isActive() const
{
return m_vrmirrorRunning;
}
#include "VRMirror.moc"
/*
* KWin XRDesktop Plugin
* Copyright 2018 Collabora Ltd.
* Author: Christoph Haag <christoph.haag@collabora.com>
* SPDX-License-Identifier: MIT
*/
#ifndef EFFECTS_VRMIRROR_H
#define EFFECTS_VRMirror_H
#include <kwineffects.h>
class VRWindow {
public:
VRWindow (KWin::EffectWindow *kwin_window)
: kwin_window(kwin_window)
{
}
// gobject_window *vr_window;
KWin::EffectWindow *kwin_window;
};
class VRMirror
: public KWin::Effect
{
Q_OBJECT
public:
VRMirror();
~VRMirror();
void paintWindow(KWin::EffectWindow* w, int mask, QRegion region, KWin::WindowPaintData& data);
void drawWindow(KWin::EffectWindow* w, int mask, QRegion region, KWin::WindowPaintData& data);
void prePaintScreen(KWin::ScreenPrePaintData &data, int time);
void prePaintWindow(KWin::EffectWindow *w, KWin::WindowPrePaintData &data, int time);
void paintEffectFrame(KWin::EffectFrame* frame, QRegion region, double opacity, double frameOpacity);
bool isActive() const;
static bool supported();
static bool enabledByDefault();
bool isMirrored(KWin::EffectWindow *kwin_window) {
for (auto& vrwin : m_mirroredWindows) {
if (vrwin->kwin_window == kwin_window)
return true;
}
return false;
}
VRWindow* removeMirrored(KWin::EffectWindow *kwin_window) {
for (auto& vrwin : m_mirroredWindows) {
if (vrwin->kwin_window == kwin_window)
return vrwin;
}
return NULL;
}
VRWindow* clear_mirrored() {
for (auto& vrwin : m_mirroredWindows) {
delete vrwin;
}
m_mirroredWindows.clear();
return NULL;
}
public Q_SLOTS:
void toggleScreenVRMirror();
void slotWindowClosed(KWin::EffectWindow *w);
void slotWindowAdded(KWin::EffectWindow* w);
protected:
bool initVR();
private:
bool m_vrmirrorInitialized;
bool m_vrmirrorRunning;
QList<VRWindow*> m_mirroredWindows;
};
#endif
#######################################
# Effect
#######################################
# Config
find_package (Qt5 REQUIRED COMPONENTS
Core
DBus
)
find_package (KF5 REQUIRED COMPONENTS
ConfigWidgets
GlobalAccel
I18n
Service
XmlGui
)
set(kwin_vrmirror_config_SRCS vrmirror_config.cpp)
qt5_add_dbus_interface(kwin_vrmirror_config_SRCS dbus.xml kwineffects_interface)
add_library(kwin_vrmirror_config MODULE ${kwin_vrmirror_config_SRCS})
target_link_libraries(kwin_vrmirror_config
Qt5::Core
Qt5::DBus
KF5::ConfigWidgets
KF5::GlobalAccel
KF5::I18n
KF5::Service
KF5::XmlGui
)
kcoreaddons_desktop_to_json(kwin_vrmirror_config vrmirror_config.desktop SERVICE_TYPES kcmodule.desktop)
install(
TARGETS
kwin_vrmirror_config
DESTINATION
${PLUGIN_INSTALL_DIR}/kwin/effects/configs
)
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.kde.kwin.Effects">
<property name="activeEffects" type="as" access="read"/>
<property name="loadedEffects" type="as" access="read"/>
<property name="listOfEffects" type="as" access="read"/>
<method name="reconfigureEffect">
<arg name="name" type="s" direction="in"/>
</method>
<method name="loadEffect">
<arg type="b" direction="out"/>
<arg name="name" type="s" direction="in"/>
</method>
<method name="toggleEffect">
<arg name="name" type="s" direction="in"/>
</method>
<method name="unloadEffect">
<arg name="name" type="s" direction="in"/>
</method>
<method name="isEffectLoaded">
<arg type="b" direction="out"/>
<arg name="name" type="s" direction="in"/>
</method>
<method name="isEffectSupported">
<arg type="b" direction="out"/>
<arg name="name" type="s" direction="in"/>
</method>
<method name="areEffectsSupported">
<arg type="ab" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;bool&gt;"/>
<arg name="names" type="as" direction="in"/>
</method>
<method name="supportInformation">
<arg type="s" direction="out"/>
<arg name="name" type="s" direction="in"/>
</method>
<method name="debug">
<arg type="s" direction="out"/>
<arg name="name" type="s" direction="in"/>
<arg name="name" type="s" direction="in"/>
</method>
</interface>
</node>
/*
* KWin XRDesktop Plugin
* Copyright 2018 Collabora Ltd.
* Author: Christoph Haag <christoph.haag@collabora.com>
* SPDX-License-Identifier: MIT
*/
#include "vrmirror_config.h"
#include <kwineffects_interface.h>
#include <QAction>
#include <KGlobalAccel>
#include <KLocalizedString>
#include <KActionCollection>
#include <KShortcutsEditor>
#include <KAboutData>
#include <KPluginFactory>
#include <QVBoxLayout>
K_PLUGIN_FACTORY_WITH_JSON(VRMirrorEffectConfigFactory,
"vrmirror_config.json",
registerPlugin<KWin::VRMirrorEffectConfig>();)
namespace KWin
{
VRMirrorEffectConfig::VRMirrorEffectConfig(QWidget* parent, const QVariantList& args) :
KCModule(KAboutData::pluginData(QStringLiteral("vrmirror")), parent, args)
{
QVBoxLayout* layout = new QVBoxLayout(this);
auto *actionCollection = new KActionCollection(this, QStringLiteral("kwin"));
actionCollection->setComponentDisplayName(i18n("KWin"));
actionCollection->setConfigGroup(QStringLiteral("VRMirror"));
actionCollection->setConfigGlobal(true);
QAction *toggleAction = actionCollection->addAction(QStringLiteral("Toggle"));
toggleAction->setText(i18n("Toggle VR Mirror"));
toggleAction->setProperty("isConfigurationAction", true);
KGlobalAccel::self()->setDefaultShortcut(toggleAction, {});
KGlobalAccel::self()->setShortcut(toggleAction, {});
mShortcutEditor = new KShortcutsEditor(actionCollection, this,
KShortcutsEditor::GlobalAction, KShortcutsEditor::LetterShortcutsDisallowed);
connect(mShortcutEditor, SIGNAL(keyChange()), this, SLOT(changed()));
layout->addWidget(mShortcutEditor);
load();
}
VRMirrorEffectConfig::~VRMirrorEffectConfig()
{
// Undo (only) unsaved changes to global key shortcuts
mShortcutEditor->undoChanges();
}
void VRMirrorEffectConfig::load()
{
KCModule::load();
emit changed(false);
}
void VRMirrorEffectConfig::save()
{
KCModule::save();
mShortcutEditor->save(); // undo() will restore to this state from now on
emit changed(false);
OrgKdeKwinEffectsInterface interface(QStringLiteral("org.kde.KWin"),
QStringLiteral("/Effects"),
QDBusConnection::sessionBus());
interface.reconfigureEffect(QStringLiteral("vrmirror"));
}
void VRMirrorEffectConfig::defaults()
{
mShortcutEditor->allDefault();
emit changed(true);
}
} // namespace
#include "vrmirror_config.moc"
[Desktop Entry]
Type=Service
X-KDE-ServiceTypes=KCModule
X-KDE-Library=kwin_vrmirror_config
X-KDE-ParentComponents=kwin_effect_vrmirror
Name=VR Desktop
/*
* KWin XRDesktop Plugin
* Copyright 2018 Collabora Ltd.
* Author: Christoph Haag <christoph.haag@collabora.com>
* SPDX-License-Identifier: MIT
*/
#ifndef KWIN_VRMIRROR_CONFIG_H
#define KWIN_VRMIRROR_CONFIG_H
#include <kcmodule.h>
class KShortcutsEditor;
namespace KWin
{
class VRMirrorEffectConfig : public KCModule
{
Q_OBJECT
public:
explicit VRMirrorEffectConfig(QWidget* parent = 0, const QVariantList& args = QVariantList());
~VRMirrorEffectConfig();
public Q_SLOTS:
virtual void save();
virtual void load();
virtual void defaults();
private:
KShortcutsEditor* mShortcutEditor;
};
} // namespace
#endif
[Desktop Entry]
Encoding=UTF-8
Name=VR Mirror
Comment=VR Mirror for Desktop Windows
Type=Service
X-KDE-ServiceTypes=KWin/Effect
X-KDE-PluginInfo-Author=Christoph Haag
X-KDE-PluginInfo-Email=christoph.haag@collabora.com
X-KDE-PluginInfo-Name=kwin_effect_vrmirror
X-KDE-PluginInfo-Version=1.0
X-KDE-PluginInfo-Category=Appearance
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true