diff --git a/CMakeLists.txt b/CMakeLists.txt index 345705729..452602b10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,713 +1,715 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR) project(KWIN) set(PROJECT_VERSION "5.13.80") set(PROJECT_VERSION_MAJOR 5) set(QT_MIN_VERSION "5.9.0") set(KF5_MIN_VERSION "5.42.0") set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH} ) find_package(ECM 5.38 REQUIRED NO_MODULE) include(FeatureSummary) include(WriteBasicConfigVersionFile) include(GenerateExportHeader) # where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS Concurrent Core DBus Quick QuickWidgets Sensors Script UiTools Widgets X11Extras ) find_package(Qt5Test ${QT_MIN_VERSION} CONFIG QUIET) set_package_properties(Qt5Test PROPERTIES PURPOSE "Required for tests" TYPE OPTIONAL ) add_feature_info("Qt5Test" Qt5Test_FOUND "Required for building tests") if (NOT Qt5Test_FOUND) set(BUILD_TESTING OFF CACHE BOOL "Build the testing tree.") endif() include(KDEInstallDirs) include(KDECMakeSettings) include(KDECompilerSettings NO_POLICY_SCOPE) include(ECMInstallIcons) include(ECMOptionalAddSubdirectory) add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0 -DQT_USE_QSTRINGBUILDER) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-inconsistent-missing-override") endif() find_package(Qt5Multimedia QUIET) set_package_properties(Qt5Multimedia PROPERTIES PURPOSE "Runtime-only dependency for effect video playback" TYPE RUNTIME ) # required frameworks by Core find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Config ConfigWidgets CoreAddons Crash GlobalAccel I18n Init Notifications Package Plasma WidgetsAddons WindowSystem IconThemes IdleTime Wayland ) # required frameworks by config modules find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Completion Declarative KCMUtils KIO TextWidgets NewStuff Service XmlGui ) find_package(Threads) set_package_properties(Threads PROPERTIES PURPOSE "Needed for VirtualTerminal support in KWin Wayland" TYPE REQUIRED ) # optional frameworks find_package(KF5Activities ${KF5_MIN_VERSION} CONFIG) set_package_properties(KF5Activities PROPERTIES PURPOSE "Enable building of KWin with kactivities support" TYPE OPTIONAL ) add_feature_info("KF5Activities" KF5Activities_FOUND "Enable building of KWin with kactivities support") find_package(KF5DocTools ${KF5_MIN_VERSION} CONFIG) set_package_properties(KF5DocTools PROPERTIES PURPOSE "Enable building documentation" TYPE OPTIONAL ) add_feature_info("KF5DocTools" KF5DocTools_FOUND "Enable building documentation") find_package(KDecoration2 5.13.0 CONFIG REQUIRED) find_package(KScreenLocker CONFIG REQUIRED) set_package_properties(KScreenLocker PROPERTIES TYPE REQUIRED PURPOSE "For screenlocker integration in kwin_wayland") find_package(Breeze 5.9.0 CONFIG) set_package_properties(Breeze PROPERTIES TYPE OPTIONAL PURPOSE "For setting the default window decoration plugin") if(${Breeze_FOUND}) if(${BREEZE_WITH_KDECORATION}) set(HAVE_BREEZE_DECO true) else() set(HAVE_BREEZE_DECO FALSE) endif() else() set(HAVE_BREEZE_DECO FALSE) endif() add_feature_info("Breeze-Decoration" HAVE_BREEZE_DECO "Default decoration plugin Breeze") find_package(EGL) set_package_properties(EGL PROPERTIES TYPE RUNTIME PURPOSE "Required to build KWin with EGL support" ) find_package(epoxy) set_package_properties(epoxy PROPERTIES DESCRIPTION "libepoxy" URL "http://github.com/anholt/libepoxy" TYPE REQUIRED PURPOSE "OpenGL dispatch library" ) set(HAVE_DL_LIBRARY FALSE) if(epoxy_HAS_GLX) find_library(DL_LIBRARY dl) if(DL_LIBRARY) set(HAVE_DL_LIBRARY TRUE) endif() endif() find_package(Wayland 1.2 REQUIRED COMPONENTS Cursor OPTIONAL_COMPONENTS Egl) set_package_properties(Wayland PROPERTIES TYPE REQUIRED PURPOSE "Required for building KWin with Wayland support" ) add_feature_info("Wayland::EGL" Wayland_Egl_FOUND "Enable building of Wayland backend and QPA with EGL support.") set(HAVE_WAYLAND_EGL FALSE) if(Wayland_Egl_FOUND) set(HAVE_WAYLAND_EGL TRUE) endif() find_package(XKB 0.7.0) set_package_properties(XKB PROPERTIES TYPE REQUIRED PURPOSE "Required for building KWin with Wayland support" ) find_package(Libinput 1.9) set_package_properties(Libinput PROPERTIES TYPE REQUIRED PURPOSE "Required for input handling on Wayland.") find_package(UDev) set_package_properties(UDev PROPERTIES URL "http://www.freedesktop.org/software/systemd/libudev/" DESCRIPTION "Linux device library." TYPE REQUIRED PURPOSE "Required for input handling on Wayland." ) find_package(Libdrm 2.4.62) set_package_properties(Libdrm PROPERTIES TYPE OPTIONAL PURPOSE "Required for drm output on Wayland.") set(HAVE_DRM FALSE) if(Libdrm_FOUND) set(HAVE_DRM TRUE) endif() find_package(gbm) set_package_properties(gbm PROPERTIES TYPE OPTIONAL PURPOSE "Required for egl ouput of drm backend.") set(HAVE_GBM FALSE) if(HAVE_DRM AND gbm_FOUND) set(HAVE_GBM TRUE) endif() find_package(libhybris) set_package_properties(libhybris PROPERTIES TYPE OPTIONAL PURPOSE "Required for libhybris backend") set(HAVE_LIBHYBRIS ${libhybris_FOUND}) find_package(X11) set_package_properties(X11 PROPERTIES DESCRIPTION "X11 libraries" URL "http://www.x.org" TYPE REQUIRED ) add_feature_info("XInput" X11_Xinput_FOUND "Required for poll-free mouse cursor updates") set(HAVE_X11_XINPUT ${X11_Xinput_FOUND}) # All the required XCB components find_package(XCB 1.10 REQUIRED COMPONENTS XCB XFIXES DAMAGE COMPOSITE SHAPE SYNC RENDER RANDR KEYSYMS IMAGE SHM GLX CURSOR ICCCM ) set_package_properties(XCB PROPERTIES TYPE REQUIRED) # and the optional XCB dependencies if (XCB_ICCCM_VERSION VERSION_LESS "0.4") set(XCB_ICCCM_FOUND FALSE) endif() add_feature_info("XCB-ICCCM" XCB_ICCCM_FOUND "Required for building test applications for KWin") find_package(X11_XCB) set_package_properties(X11_XCB PROPERTIES PURPOSE "Required for building X11 windowed backend of kwin_wayland" TYPE OPTIONAL) # dependencies for QPA plugin find_package(Qt5FontDatabaseSupport REQUIRED) find_package(Qt5ThemeSupport REQUIRED) find_package(Qt5EventDispatcherSupport 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." ) find_package(Xwayland) set_package_properties(Xwayland PROPERTIES URL "http://x.org" DESCRIPTION "Xwayland X server" TYPE RUNTIME PURPOSE "Needed for running kwin_wayland" ) find_package(Libcap) set_package_properties(Libcap PROPERTIES TYPE OPTIONAL PURPOSE "Needed for running kwin_wayland with real-time scheduling policy" ) set(HAVE_LIBCAP ${Libcap_FOUND}) include(ECMQMLModules) ecm_find_qmlmodule(QtQuick 2.3) ecm_find_qmlmodule(QtQuick.Controls 1.2) ecm_find_qmlmodule(QtQuick.Layouts 1.3) ecm_find_qmlmodule(QtQuick.VirtualKeyboard 2.1) ecm_find_qmlmodule(QtQuick.Window 2.1) ecm_find_qmlmodule(QtMultimedia 5.0) ecm_find_qmlmodule(org.kde.kquickcontrolsaddons 2.0) ecm_find_qmlmodule(org.kde.plasma.core 2.0) ecm_find_qmlmodule(org.kde.plasma.components 2.0) ########### configure tests ############### include(CMakeDependentOption) option(KWIN_BUILD_DECORATIONS "Enable building of KWin decorations." ON) option(KWIN_BUILD_KCMS "Enable building of KWin configuration modules." ON) option(KWIN_BUILD_TABBOX "Enable building of KWin Tabbox functionality" ON) option(KWIN_BUILD_XRENDER_COMPOSITING "Enable building of KWin with XRender Compositing support" ON) cmake_dependent_option(KWIN_BUILD_ACTIVITIES "Enable building of KWin with kactivities support" ON "KF5Activities_FOUND" OFF) # Binary name of KWin set(KWIN_NAME "kwin") set(KWIN_INTERNAL_NAME_X11 "kwin_x11") set(KWIN_INTERNAL_NAME_WAYLAND "kwin_wayland") set(KWIN_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) # KWIN_HAVE_XRENDER_COMPOSITING - whether XRender-based compositing support is available: may be disabled if( KWIN_BUILD_XRENDER_COMPOSITING ) set( KWIN_HAVE_XRENDER_COMPOSITING 1 ) endif() include_directories(${XKB_INCLUDE_DIR}) include_directories(${epoxy_INCLUDE_DIR}) set(HAVE_EPOXY_GLX ${epoxy_HAS_GLX}) # for things that are also used by kwin libraries configure_file(libkwineffects/kwinconfig.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/libkwineffects/kwinconfig.h ) # for kwin internal things set(HAVE_X11_XCB ${X11_XCB_FOUND}) include(CheckIncludeFile) include(CheckIncludeFiles) include(CheckSymbolExists) check_include_files(unistd.h HAVE_UNISTD_H) check_include_files(malloc.h HAVE_MALLOC_H) check_include_file("sys/prctl.h" HAVE_SYS_PRCTL_H) check_symbol_exists(PR_SET_DUMPABLE "sys/prctl.h" HAVE_PR_SET_DUMPABLE) check_symbol_exists(PR_SET_PDEATHSIG "sys/prctl.h" HAVE_PR_SET_PDEATHSIG) check_include_file("sys/procctl.h" HAVE_SYS_PROCCTL_H) check_symbol_exists(PROC_TRACE_CTL "sys/procctl.h" HAVE_PROC_TRACE_CTL) if (HAVE_PR_SET_DUMPABLE OR HAVE_PROC_TRACE_CTL) set(CAN_DISABLE_PTRACE TRUE) endif() add_feature_info("prctl/procctl tracing control" CAN_DISABLE_PTRACE "Required for disallowing ptrace on kwin_wayland process") check_include_file("sys/sysmacros.h" HAVE_SYS_SYSMACROS_H) configure_file(config-kwin.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kwin.h ) check_include_file("linux/vt.h" HAVE_LINUX_VT_H) add_feature_info("linux/vt.h" HAVE_LINUX_VT_H "Required for virtual terminal support under wayland") check_include_file("linux/fb.h" HAVE_LINUX_FB_H) add_feature_info("linux/fb.h" HAVE_LINUX_FB_H "Required for the fbdev backend") check_symbol_exists(SCHED_RESET_ON_FORK "sched.h" HAVE_SCHED_RESET_ON_FORK) add_feature_info("SCHED_RESET_ON_FORK" HAVE_SCHED_RESET_ON_FORK "Required for running kwin_wayland with real-time scheduling") ########### global ############### set(kwin_effects_dbus_xml ${CMAKE_CURRENT_SOURCE_DIR}/org.kde.kwin.Effects.xml) include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/libkwineffects ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libkwineffects ${CMAKE_CURRENT_SOURCE_DIR}/effects ${CMAKE_CURRENT_SOURCE_DIR}/tabbox ${CMAKE_CURRENT_SOURCE_DIR}/platformsupport ) add_subdirectory( libkwineffects ) if(KWIN_BUILD_KCMS) add_subdirectory( kcmkwin ) endif() add_subdirectory( data ) add_subdirectory( effects ) add_subdirectory( scripts ) add_subdirectory( tabbox ) add_subdirectory(scripting) add_subdirectory(helpers) ########### next target ############### set(kwin_KDEINIT_SRCS workspace.cpp dbusinterface.cpp abstract_client.cpp client.cpp client_machine.cpp cursor.cpp debug_console.cpp tabgroup.cpp focuschain.cpp globalshortcuts.cpp input.cpp input_event.cpp input_event_spy.cpp keyboard_input.cpp keyboard_layout.cpp keyboard_layout_switching.cpp keyboard_repeat.cpp pointer_input.cpp touch_input.cpp netinfo.cpp placement.cpp atoms.cpp utils.cpp layers.cpp main.cpp options.cpp outline.cpp events.cpp killwindow.cpp geometrytip.cpp screens.cpp shadow.cpp sm.cpp group.cpp manage.cpp overlaywindow.cpp activation.cpp useractions.cpp geometry.cpp rules.cpp composite.cpp toplevel.cpp unmanaged.cpp scene.cpp screenlockerwatcher.cpp thumbnailitem.cpp lanczosfilter.cpp deleted.cpp effects.cpp effectloader.cpp virtualdesktops.cpp xcbutils.cpp x11eventfilter.cpp logind.cpp onscreennotification.cpp osd.cpp screenedge.cpp scripting/scripting.cpp scripting/workspace_wrapper.cpp scripting/meta.cpp scripting/scriptedeffect.cpp scripting/scriptingutils.cpp scripting/timer.cpp scripting/scripting_model.cpp scripting/dbuscall.cpp scripting/screenedgeitem.cpp scripting/scripting_logging.cpp decorations/decoratedclient.cpp decorations/decorationbridge.cpp decorations/decorationpalette.cpp decorations/settings.cpp decorations/decorationrenderer.cpp decorations/decorations_logging.cpp platform.cpp shell_client.cpp wayland_server.cpp wayland_cursor_theme.cpp virtualkeyboard.cpp virtualkeyboard_dbus.cpp appmenu.cpp modifier_only_shortcuts.cpp xkb.cpp gestures.cpp popup_input_filter.cpp colorcorrection/manager.cpp colorcorrection/colorcorrectdbusinterface.cpp colorcorrection/suncalc.cpp abstract_opengl_context_attribute_builder.cpp egl_context_attribute_builder.cpp was_user_interaction_x11_filter.cpp moving_client_x11_filter.cpp window_property_notify_x11_filter.cpp rootinfo_filter.cpp orientation_sensor.cpp idle_inhibition.cpp libinput/context.cpp libinput/connection.cpp libinput/device.cpp libinput/events.cpp libinput/libinput_logging.cpp udev.cpp ) include(ECMQtDeclareLoggingCategory) ecm_qt_declare_logging_category(kwin_KDEINIT_SRCS HEADER colorcorrect_logging.h IDENTIFIER KWIN_COLORCORRECTION CATEGORY_NAME kwin_colorcorrection DEFAULT_SEVERITY Critical ) if(KWIN_BUILD_TABBOX) set( kwin_KDEINIT_SRCS ${kwin_KDEINIT_SRCS} tabbox/tabbox.cpp tabbox/clientmodel.cpp tabbox/desktopchain.cpp tabbox/desktopmodel.cpp tabbox/switcheritem.cpp tabbox/tabboxconfig.cpp tabbox/tabboxhandler.cpp tabbox/tabbox_logging.cpp tabbox/x11_filter.cpp ) endif() if(KWIN_BUILD_ACTIVITIES) set( kwin_KDEINIT_SRCS ${kwin_KDEINIT_SRCS} activities.cpp ) endif() if (HAVE_LINUX_VT_H) set(kwin_KDEINIT_SRCS ${kwin_KDEINIT_SRCS} virtual_terminal.cpp ) endif() kconfig_add_kcfg_files(kwin_KDEINIT_SRCS settings.kcfgc) kconfig_add_kcfg_files(kwin_KDEINIT_SRCS colorcorrection/colorcorrect_settings.kcfgc) qt5_add_dbus_adaptor( kwin_KDEINIT_SRCS org.kde.KWin.xml dbusinterface.h KWin::DBusInterface ) qt5_add_dbus_adaptor( kwin_KDEINIT_SRCS org.kde.kwin.Compositing.xml dbusinterface.h KWin::CompositorDBusInterface ) qt5_add_dbus_adaptor( kwin_KDEINIT_SRCS org.kde.kwin.ColorCorrect.xml colorcorrection/colorcorrectdbusinterface.h KWin::ColorCorrect::ColorCorrectDBusInterface ) qt5_add_dbus_adaptor( kwin_KDEINIT_SRCS ${kwin_effects_dbus_xml} effects.h KWin::EffectsHandlerImpl ) qt5_add_dbus_adaptor( kwin_KDEINIT_SRCS org.kde.kwin.OrientationSensor.xml orientation_sensor.h KWin::OrientationSensor) qt5_add_dbus_interface( kwin_KDEINIT_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/org.freedesktop.ScreenSaver.xml screenlocker_interface) qt5_add_dbus_interface( kwin_KDEINIT_SRCS org.kde.kappmenu.xml appmenu_interface ) qt5_add_resources( kwin_KDEINIT_SRCS resources.qrc ) ki18n_wrap_ui(kwin_KDEINIT_SRCS debug_console.ui shortcutdialog.ui ) ########### target link libraries ############### set(kwin_OWN_LIBS kwineffects kwin4_effect_builtins ) set(kwin_QT_LIBS Qt5::Concurrent Qt5::DBus Qt5::Quick Qt5::Sensors Qt5::Script ) set(kwin_KDE_LIBS KF5::ConfigCore KF5::CoreAddons KF5::ConfigWidgets KF5::GlobalAccel KF5::GlobalAccelPrivate KF5::I18n KF5::Notifications KF5::Package KF5::Plasma KF5::WindowSystem KF5::QuickAddons KDecoration2::KDecoration KDecoration2::KDecoration2Private PW::KScreenLocker ) set(kwin_XLIB_LIBS ${X11_X11_LIB} ${X11_ICE_LIB} ${X11_SM_LIB} ) set(kwin_XCB_LIBS XCB::XCB XCB::XFIXES XCB::DAMAGE XCB::COMPOSITE XCB::SHAPE XCB::SYNC XCB::RENDER XCB::RANDR XCB::KEYSYMS XCB::SHM XCB::GLX XCB::ICCCM ) set(kwin_WAYLAND_LIBS XKB::XKB KF5::WaylandClient KF5::WaylandServer Wayland::Cursor ${CMAKE_THREAD_LIBS_INIT} ) if(KWIN_BUILD_ACTIVITIES) set(kwin_KDE_LIBS ${kwin_KDE_LIBS} KF5::Activities) endif() set(kwinLibs ${kwin_OWN_LIBS} ${kwin_QT_LIBS} ${kwin_KDE_LIBS} ${kwin_XLIB_LIBS} ${kwin_XCB_LIBS} ${kwin_WAYLAND_LIBS} ${UDEV_LIBS} Libinput::Libinput ) add_library(kwin SHARED ${kwin_KDEINIT_SRCS}) set_target_properties(kwin PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} ) target_link_libraries(kwin ${kwinLibs}) generate_export_header(kwin EXPORT_FILE_NAME kwin_export.h) target_link_libraries(kwin kwinglutils ${epoxy_LIBRARY}) kf5_add_kdeinit_executable(kwin_x11 main_x11.cpp) target_link_libraries(kdeinit_kwin_x11 kwin KF5::Crash Qt5::X11Extras) install(TARGETS kwin ${INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY NAMELINK_SKIP ) install(TARGETS kdeinit_kwin_x11 ${INSTALL_TARGETS_DEFAULT_ARGS} ) install(TARGETS kwin_x11 ${INSTALL_TARGETS_DEFAULT_ARGS} ) add_executable(kwin_wayland tabletmodemanager.cpp main_wayland.cpp) target_link_libraries(kwin_wayland kwin) if (HAVE_LIBCAP) target_link_libraries(kwin_wayland ${Libcap_LIBRARIES}) endif() install(TARGETS kwin_wayland ${INSTALL_TARGETS_DEFAULT_ARGS} ) if (HAVE_LIBCAP) install( CODE "execute_process( COMMAND ${SETCAP_EXECUTABLE} CAP_SYS_NICE=+ep \$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/kwin_wayland)" ) endif() add_subdirectory(platformsupport) add_subdirectory(plugins) ########### install files ############### install( FILES kwin.kcfg DESTINATION ${KCFG_INSTALL_DIR} RENAME ${KWIN_NAME}.kcfg ) install( FILES colorcorrection/colorcorrect_settings.kcfg DESTINATION ${KCFG_INSTALL_DIR} RENAME ${KWIN_NAME}_colorcorrect.kcfg ) install( FILES kwin.notifyrc DESTINATION ${KNOTIFYRC_INSTALL_DIR} RENAME ${KWIN_NAME}.notifyrc) install( FILES org.kde.KWin.xml org.kde.kwin.Compositing.xml org.kde.kwin.ColorCorrect.xml org.kde.kwin.Effects.xml DESTINATION ${KDE_INSTALL_DBUSINTERFACEDIR} ) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/kwin_export.h DESTINATION ${INCLUDE_INSTALL_DIR} COMPONENT Devel) # Install the KWin/Script service type install( FILES scripting/kwinscript.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR} ) ecm_install_icons( ICONS 16-apps-kwin.png 32-apps-kwin.png 48-apps-kwin.png sc-apps-kwin.svgz DESTINATION ${ICON_INSTALL_DIR} THEME hicolor ) add_subdirectory(qml) add_subdirectory(packageplugins) if (BUILD_TESTING) add_subdirectory(autotests) add_subdirectory(tests) endif() if (KF5DocTools_FOUND) add_subdirectory(doc) endif() +add_subdirectory(kconf_update) + feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) include(CMakePackageConfigHelpers) set(CMAKECONFIG_INSTALL_DIR "${CMAKECONFIG_INSTALL_PREFIX}/KWinDBusInterface") configure_package_config_file(KWinDBusInterfaceConfig.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/KWinDBusInterfaceConfig.cmake" PATH_VARS KDE_INSTALL_DBUSINTERFACEDIR INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/KWinDBusInterfaceConfig.cmake DESTINATION ${CMAKECONFIG_INSTALL_DIR}) diff --git a/autotests/integration/effects/slidingpopups_test.cpp b/autotests/integration/effects/slidingpopups_test.cpp index c40cde30d..0622d53a7 100644 --- a/autotests/integration/effects/slidingpopups_test.cpp +++ b/autotests/integration/effects/slidingpopups_test.cpp @@ -1,374 +1,370 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2016 Martin Gräßlin 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 "kwin_wayland_test.h" #include "composite.h" #include "effects.h" #include "effectloader.h" #include "cursor.h" #include "platform.h" #include "shell_client.h" #include "wayland_server.h" #include "workspace.h" #include "effect_builtins.h" #include #include #include #include #include #include #include #include using namespace KWin; static const QString s_socketName = QStringLiteral("wayland_test_effects_slidingpopups-0"); class SlidingPopupsTest : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void init(); void cleanup(); void testWithOtherEffect_data(); void testWithOtherEffect(); void testWithOtherEffectWayland_data(); void testWithOtherEffectWayland(); }; void SlidingPopupsTest::initTestCase() { qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated); QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); // disable all effects - we don't want to have it interact with the rendering auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); KConfigGroup plugins(config, QStringLiteral("Plugins")); ScriptedEffectLoader loader; const auto builtinNames = BuiltInEffects::availableEffectNames() << loader.listOfKnownEffects(); for (QString name : builtinNames) { plugins.writeEntry(name + QStringLiteral("Enabled"), false); } KConfigGroup wobblyGroup = config->group("Effect-Wobbly"); wobblyGroup.writeEntry(QStringLiteral("Settings"), QStringLiteral("Custom")); wobblyGroup.writeEntry(QStringLiteral("OpenEffect"), true); wobblyGroup.writeEntry(QStringLiteral("CloseEffect"), true); config->sync(); kwinApp()->setConfig(config); if (QFile::exists(QStringLiteral("/dev/dri/card0"))) { qputenv("KWIN_COMPOSE", QByteArrayLiteral("O2")); } qputenv("KWIN_EFFECTS_FORCE_ANIMATIONS", "1"); kwinApp()->start(); QVERIFY(workspaceCreatedSpy.wait()); QVERIFY(Compositor::self()); } void SlidingPopupsTest::init() { QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::Decoration)); } void SlidingPopupsTest::cleanup() { Test::destroyWaylandConnection(); EffectsHandlerImpl *e = static_cast(effects); while (!e->loadedEffects().isEmpty()) { const QString effect = e->loadedEffects().first(); e->unloadEffect(effect); QVERIFY(!e->isEffectLoaded(effect)); } } struct XcbConnectionDeleter { static inline void cleanup(xcb_connection_t *pointer) { xcb_disconnect(pointer); } }; void SlidingPopupsTest::testWithOtherEffect_data() { QTest::addColumn("effectsToLoad"); - QTest::newRow("scale, slide") << QStringList{QStringLiteral("kwin4_effect_scalein"), QStringLiteral("slidingpopups")}; - QTest::newRow("slide, scale") << QStringList{QStringLiteral("slidingpopups"), QStringLiteral("kwin4_effect_scalein")}; QTest::newRow("fade, slide") << QStringList{QStringLiteral("kwin4_effect_fade"), QStringLiteral("slidingpopups")}; QTest::newRow("slide, fade") << QStringList{QStringLiteral("slidingpopups"), QStringLiteral("kwin4_effect_fade")}; if (effects->compositingType() & KWin::OpenGLCompositing) { QTest::newRow("glide, slide") << QStringList{QStringLiteral("glide"), QStringLiteral("slidingpopups")}; QTest::newRow("slide, glide") << QStringList{QStringLiteral("slidingpopups"), QStringLiteral("glide")}; QTest::newRow("wobblywindows, slide") << QStringList{QStringLiteral("wobblywindows"), QStringLiteral("slidingpopups")}; QTest::newRow("slide, wobblywindows") << QStringList{QStringLiteral("slidingpopups"), QStringLiteral("wobblywindows")}; QTest::newRow("fallapart, slide") << QStringList{QStringLiteral("fallapart"), QStringLiteral("slidingpopups")}; QTest::newRow("slide, fallapart") << QStringList{QStringLiteral("slidingpopups"), QStringLiteral("fallapart")}; } } void SlidingPopupsTest::testWithOtherEffect() { // this test verifies that slidingpopups effect grabs the window added role // independently of the sequence how the effects are loaded. // see BUG 336866 EffectsHandlerImpl *e = static_cast(effects); // find the effectsloader auto effectloader = e->findChild(); QVERIFY(effectloader); QSignalSpy effectLoadedSpy(effectloader, &AbstractEffectLoader::effectLoaded); QVERIFY(effectLoadedSpy.isValid()); Effect *slidingPoupus = nullptr; Effect *otherEffect = nullptr; QFETCH(QStringList, effectsToLoad); for (const QString &effectName : effectsToLoad) { QVERIFY(!e->isEffectLoaded(effectName)); QVERIFY(e->loadEffect(effectName)); QVERIFY(e->isEffectLoaded(effectName)); QCOMPARE(effectLoadedSpy.count(), 1); Effect *effect = effectLoadedSpy.first().first().value(); if (effectName == QStringLiteral("slidingpopups")) { slidingPoupus = effect; } else { otherEffect = effect; } effectLoadedSpy.clear(); } QVERIFY(slidingPoupus); QVERIFY(otherEffect); QVERIFY(!slidingPoupus->isActive()); QVERIFY(!otherEffect->isActive()); // give the compositor some time to render QTest::qWait(50); QSignalSpy windowAddedSpy(effects, &EffectsHandler::windowAdded); QVERIFY(windowAddedSpy.isValid()); // create an xcb window QScopedPointer c(xcb_connect(nullptr, nullptr)); QVERIFY(!xcb_connection_has_error(c.data())); const QRect windowGeometry(0, 0, 100, 200); xcb_window_t w = xcb_generate_id(c.data()); xcb_create_window(c.data(), XCB_COPY_FROM_PARENT, w, rootWindow(), windowGeometry.x(), windowGeometry.y(), windowGeometry.width(), windowGeometry.height(), 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr); xcb_size_hints_t hints; memset(&hints, 0, sizeof(hints)); xcb_icccm_size_hints_set_position(&hints, 1, windowGeometry.x(), windowGeometry.y()); xcb_icccm_size_hints_set_size(&hints, 1, windowGeometry.width(), windowGeometry.height()); xcb_icccm_set_wm_normal_hints(c.data(), w, &hints); NETWinInfo winInfo(c.data(), w, rootWindow(), NET::Properties(), NET::Properties2()); winInfo.setWindowType(NET::Normal); // and get the slide atom const QByteArray effectAtomName = QByteArrayLiteral("_KDE_SLIDE"); xcb_intern_atom_cookie_t atomCookie = xcb_intern_atom_unchecked(c.data(), false, effectAtomName.length(), effectAtomName.constData()); const int size = 2; int32_t data[size]; data[0] = 0; data[1] = 0; QScopedPointer atom(xcb_intern_atom_reply(c.data(), atomCookie, nullptr)); QVERIFY(!atom.isNull()); xcb_change_property(c.data(), XCB_PROP_MODE_REPLACE, w, atom->atom, atom->atom, 32, size, data); xcb_map_window(c.data(), w); xcb_flush(c.data()); // we should get a client for it QSignalSpy windowCreatedSpy(workspace(), &Workspace::clientAdded); QVERIFY(windowCreatedSpy.isValid()); QVERIFY(windowCreatedSpy.wait()); Client *client = windowCreatedSpy.first().first().value(); QVERIFY(client); QCOMPARE(client->window(), w); QVERIFY(client->isNormalWindow()); // sliding popups should be active QVERIFY(windowAddedSpy.wait()); QTRY_VERIFY(slidingPoupus->isActive()); QVERIFY(!otherEffect->isActive()); // wait till effect ends QTRY_VERIFY(!slidingPoupus->isActive()); QTest::qWait(300); QVERIFY(!otherEffect->isActive()); // and destroy the window again xcb_unmap_window(c.data(), w); xcb_flush(c.data()); QSignalSpy windowClosedSpy(client, &Client::windowClosed); QVERIFY(windowClosedSpy.isValid()); QSignalSpy windowDeletedSpy(effects, &EffectsHandler::windowDeleted); QVERIFY(windowDeletedSpy.isValid()); QVERIFY(windowClosedSpy.wait()); // again we should have the sliding popups active QVERIFY(slidingPoupus->isActive()); QVERIFY(!otherEffect->isActive()); QVERIFY(windowDeletedSpy.wait()); QCOMPARE(windowDeletedSpy.count(), 1); QTRY_VERIFY(!slidingPoupus->isActive()); QTest::qWait(300); QVERIFY(!otherEffect->isActive()); xcb_destroy_window(c.data(), w); c.reset(); } void SlidingPopupsTest::testWithOtherEffectWayland_data() { QTest::addColumn("effectsToLoad"); - QTest::newRow("scale, slide") << QStringList{QStringLiteral("kwin4_effect_scalein"), QStringLiteral("slidingpopups")}; - QTest::newRow("slide, scale") << QStringList{QStringLiteral("slidingpopups"), QStringLiteral("kwin4_effect_scalein")}; QTest::newRow("fade, slide") << QStringList{QStringLiteral("kwin4_effect_fade"), QStringLiteral("slidingpopups")}; QTest::newRow("slide, fade") << QStringList{QStringLiteral("slidingpopups"), QStringLiteral("kwin4_effect_fade")}; if (effects->compositingType() & KWin::OpenGLCompositing) { QTest::newRow("glide, slide") << QStringList{QStringLiteral("glide"), QStringLiteral("slidingpopups")}; QTest::newRow("slide, glide") << QStringList{QStringLiteral("slidingpopups"), QStringLiteral("glide")}; QTest::newRow("wobblywindows, slide") << QStringList{QStringLiteral("wobblywindows"), QStringLiteral("slidingpopups")}; QTest::newRow("slide, wobblywindows") << QStringList{QStringLiteral("slidingpopups"), QStringLiteral("wobblywindows")}; QTest::newRow("fallapart, slide") << QStringList{QStringLiteral("fallapart"), QStringLiteral("slidingpopups")}; QTest::newRow("slide, fallapart") << QStringList{QStringLiteral("slidingpopups"), QStringLiteral("fallapart")}; } } void SlidingPopupsTest::testWithOtherEffectWayland() { // this test verifies that slidingpopups effect grabs the window added role // independently of the sequence how the effects are loaded. // see BUG 336866 // the test is like testWithOtherEffect, but simulates using a Wayland window EffectsHandlerImpl *e = static_cast(effects); // find the effectsloader auto effectloader = e->findChild(); QVERIFY(effectloader); QSignalSpy effectLoadedSpy(effectloader, &AbstractEffectLoader::effectLoaded); QVERIFY(effectLoadedSpy.isValid()); Effect *slidingPoupus = nullptr; Effect *otherEffect = nullptr; QFETCH(QStringList, effectsToLoad); for (const QString &effectName : effectsToLoad) { QVERIFY(!e->isEffectLoaded(effectName)); QVERIFY(e->loadEffect(effectName)); QVERIFY(e->isEffectLoaded(effectName)); QCOMPARE(effectLoadedSpy.count(), 1); Effect *effect = effectLoadedSpy.first().first().value(); if (effectName == QStringLiteral("slidingpopups")) { slidingPoupus = effect; } else { otherEffect = effect; } effectLoadedSpy.clear(); } QVERIFY(slidingPoupus); QVERIFY(otherEffect); QVERIFY(!slidingPoupus->isActive()); QVERIFY(!otherEffect->isActive()); QSignalSpy windowAddedSpy(effects, &EffectsHandler::windowAdded); QVERIFY(windowAddedSpy.isValid()); using namespace KWayland::Client; // the test created the slide protocol, let's create a Registry and listen for it QScopedPointer registry(new Registry); registry->create(Test::waylandConnection()); QSignalSpy interfacesAnnouncedSpy(registry.data(), &Registry::interfacesAnnounced); QVERIFY(interfacesAnnouncedSpy.isValid()); registry->setup(); QVERIFY(interfacesAnnouncedSpy.wait()); auto slideInterface = registry->interface(Registry::Interface::Slide); QVERIFY(slideInterface.name != 0); QScopedPointer slideManager(registry->createSlideManager(slideInterface.name, slideInterface.version)); QVERIFY(slideManager); // create Wayland window QScopedPointer surface(Test::createSurface()); QVERIFY(surface); QScopedPointer slide(slideManager->createSlide(surface.data())); slide->setLocation(Slide::Location::Left); slide->commit(); QScopedPointer shellSurface(Test::createShellSurface(surface.data())); QVERIFY(shellSurface); QCOMPARE(windowAddedSpy.count(), 0); auto client = Test::renderAndWaitForShown(surface.data(), QSize(10, 20), Qt::blue); QVERIFY(client); QVERIFY(client->isNormalWindow()); // sliding popups should be active QCOMPARE(windowAddedSpy.count(), 1); QTRY_VERIFY(slidingPoupus->isActive()); QVERIFY(!otherEffect->isActive()); // wait till effect ends QTRY_VERIFY(!slidingPoupus->isActive()); QTest::qWait(300); QVERIFY(!otherEffect->isActive()); // and destroy the window again shellSurface.reset(); surface.reset(); QSignalSpy windowClosedSpy(client, &Client::windowClosed); QVERIFY(windowClosedSpy.isValid()); QSignalSpy windowDeletedSpy(effects, &EffectsHandler::windowDeleted); QVERIFY(windowDeletedSpy.isValid()); QVERIFY(windowClosedSpy.wait()); // again we should have the sliding popups active QVERIFY(slidingPoupus->isActive()); QVERIFY(!otherEffect->isActive()); QVERIFY(windowDeletedSpy.wait()); QCOMPARE(windowDeletedSpy.count(), 1); QTRY_VERIFY(!slidingPoupus->isActive()); QTest::qWait(300); QVERIFY(!otherEffect->isActive()); } WAYLANDTEST_MAIN(SlidingPopupsTest) #include "slidingpopups_test.moc" diff --git a/autotests/test_plugin_effectloader.cpp b/autotests/test_plugin_effectloader.cpp index 5143ee08a..841c9bf5c 100644 --- a/autotests/test_plugin_effectloader.cpp +++ b/autotests/test_plugin_effectloader.cpp @@ -1,420 +1,419 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2014 Martin Gräßlin 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 "../effectloader.h" #include "mock_effectshandler.h" #include "../scripting/scriptedeffect.h" // for mocking ScriptedEffect::create // KDE #include #include #include // Qt #include #include Q_DECLARE_METATYPE(KWin::CompositingType) Q_DECLARE_METATYPE(KWin::LoadEffectFlag) Q_DECLARE_METATYPE(KWin::LoadEffectFlags) Q_DECLARE_METATYPE(KWin::Effect*) Q_LOGGING_CATEGORY(KWIN_CORE, "kwin_core") namespace KWin { ScriptedEffect *ScriptedEffect::create(const KPluginMetaData&) { return nullptr; } bool ScriptedEffect::supported() { return true; } } class TestPluginEffectLoader : public QObject { Q_OBJECT private Q_SLOTS: void testHasEffect_data(); void testHasEffect(); void testKnownEffects(); void testSupported_data(); void testSupported(); void testLoadEffect_data(); void testLoadEffect(); void testLoadPluginEffect_data(); void testLoadPluginEffect(); void testLoadAllEffects(); void testCancelLoadAllEffects(); }; void TestPluginEffectLoader::testHasEffect_data() { QTest::addColumn("name"); QTest::addColumn("expected"); // all the built-in effects should fail QTest::newRow("blur") << QStringLiteral("blur") << false; QTest::newRow("ColorPicker") << QStringLiteral("colorpicker") << false; QTest::newRow("Contrast") << QStringLiteral("contrast") << false; QTest::newRow("CoverSwitch") << QStringLiteral("coverswitch") << false; QTest::newRow("Cube") << QStringLiteral("cube") << false; QTest::newRow("CubeSlide") << QStringLiteral("cubeslide") << false; QTest::newRow("DesktopGrid") << QStringLiteral("desktopgrid") << false; QTest::newRow("DimInactive") << QStringLiteral("diminactive") << false; QTest::newRow("DimScreen") << QStringLiteral("dimscreen") << false; QTest::newRow("FallApart") << QStringLiteral("fallapart") << false; QTest::newRow("FlipSwitch") << QStringLiteral("flipswitch") << false; QTest::newRow("Glide") << QStringLiteral("glide") << false; QTest::newRow("HighlightWindow") << QStringLiteral("highlightwindow") << false; QTest::newRow("Invert") << QStringLiteral("invert") << false; QTest::newRow("Kscreen") << QStringLiteral("kscreen") << false; QTest::newRow("LookingGlass") << QStringLiteral("lookingglass") << false; QTest::newRow("MagicLamp") << QStringLiteral("magiclamp") << false; QTest::newRow("Magnifier") << QStringLiteral("magnifier") << false; QTest::newRow("MinimizeAnimation") << QStringLiteral("minimizeanimation") << false; QTest::newRow("MouseClick") << QStringLiteral("mouseclick") << false; QTest::newRow("MouseMark") << QStringLiteral("mousemark") << false; QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << false; QTest::newRow("Resize") << QStringLiteral("resize") << false; QTest::newRow("Scale") << QStringLiteral("scale") << false; QTest::newRow("ScreenEdge") << QStringLiteral("screenedge") << false; QTest::newRow("ScreenShot") << QStringLiteral("screenshot") << false; QTest::newRow("Sheet") << QStringLiteral("sheet") << false; QTest::newRow("ShowFps") << QStringLiteral("showfps") << false; QTest::newRow("ShowPaint") << QStringLiteral("showpaint") << false; QTest::newRow("Slide") << QStringLiteral("slide") << false; QTest::newRow("SlideBack") << QStringLiteral("slideback") << false; QTest::newRow("SlidingPopups") << QStringLiteral("slidingpopups") << false; QTest::newRow("SnapHelper") << QStringLiteral("snaphelper") << false; QTest::newRow("StartupFeedback") << QStringLiteral("startupfeedback") << false; QTest::newRow("ThumbnailAside") << QStringLiteral("thumbnailaside") << false; QTest::newRow("TrackMouse") << QStringLiteral("trackmouse") << false; QTest::newRow("WindowGeometry") << QStringLiteral("windowgeometry") << false; QTest::newRow("WobblyWindows") << QStringLiteral("wobblywindows") << false; QTest::newRow("Zoom") << QStringLiteral("zoom") << false; QTest::newRow("Non Existing") << QStringLiteral("InvalidName") << false; // all the scripted effects should fail QTest::newRow("Fade") << QStringLiteral("kwin4_effect_fade") << false; QTest::newRow("FadeDesktop") << QStringLiteral("kwin4_effect_fadedesktop") << false; QTest::newRow("DialogParent") << QStringLiteral("kwin4_effect_dialogparent") << false; QTest::newRow("Login") << QStringLiteral("kwin4_effect_login") << false; QTest::newRow("Logout") << QStringLiteral("kwin4_effect_logout") << false; QTest::newRow("Maximize") << QStringLiteral("kwin4_effect_maximize") << false; - QTest::newRow("ScaleIn") << QStringLiteral("kwin4_effect_scalein") << false; QTest::newRow("Translucency") << QStringLiteral("kwin4_effect_translucency") << false; // and the fake effects we use here QTest::newRow("fakeeffectplugin") << QStringLiteral("fakeeffectplugin") << true; QTest::newRow("fakeeffectplugin CS") << QStringLiteral("fakeEffectPlugin") << true; QTest::newRow("effectversion") << QStringLiteral("effectversion") << true; } void TestPluginEffectLoader::testHasEffect() { QFETCH(QString, name); QFETCH(bool, expected); KWin::PluginEffectLoader loader; loader.setPluginSubDirectory(QString()); QCOMPARE(loader.hasEffect(name), expected); } void TestPluginEffectLoader::testKnownEffects() { QStringList expectedEffects; expectedEffects << QStringLiteral("fakeeffectplugin") << QStringLiteral("effectversion"); KWin::PluginEffectLoader loader; loader.setPluginSubDirectory(QString()); QStringList result = loader.listOfKnownEffects(); // at least as many effects as we expect - system running the test could have more effects QVERIFY(result.size() >= expectedEffects.size()); for (const QString &effect : expectedEffects) { QVERIFY(result.contains(effect)); } } void TestPluginEffectLoader::testSupported_data() { QTest::addColumn("name"); QTest::addColumn("expected"); QTest::addColumn("type"); const KWin::CompositingType xc = KWin::XRenderCompositing; const KWin::CompositingType oc = KWin::OpenGL2Compositing; QTest::newRow("invalid") << QStringLiteral("blur") << false << xc; QTest::newRow("fake - xrender") << QStringLiteral("fakeeffectplugin") << false << xc; QTest::newRow("fake - opengl") << QStringLiteral("fakeeffectplugin") << true << oc; QTest::newRow("fake - CS") << QStringLiteral("fakeEffectPlugin") << true << oc; QTest::newRow("version") << QStringLiteral("effectversion") << false << xc; } void TestPluginEffectLoader::testSupported() { QFETCH(QString, name); QFETCH(bool, expected); QFETCH(KWin::CompositingType, type); MockEffectsHandler mockHandler(type); KWin::PluginEffectLoader loader; loader.setPluginSubDirectory(QString()); QCOMPARE(loader.isEffectSupported(name), expected); } void TestPluginEffectLoader::testLoadEffect_data() { QTest::addColumn("name"); QTest::addColumn("expected"); QTest::addColumn("type"); const KWin::CompositingType xc = KWin::XRenderCompositing; const KWin::CompositingType oc = KWin::OpenGL2Compositing; QTest::newRow("invalid") << QStringLiteral("slide") << false << xc; QTest::newRow("fake - xrender") << QStringLiteral("fakeeffectplugin") << false << xc; QTest::newRow("fake - opengl") << QStringLiteral("fakeeffectplugin") << true << oc; QTest::newRow("fake - CS") << QStringLiteral("fakeEffectPlugin") << true << oc; QTest::newRow("version") << QStringLiteral("effectversion") << false << xc; } void TestPluginEffectLoader::testLoadEffect() { QFETCH(QString, name); QFETCH(bool, expected); QFETCH(KWin::CompositingType, type); MockEffectsHandler mockHandler(type); KWin::PluginEffectLoader loader; loader.setPluginSubDirectory(QString()); KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); loader.setConfig(config); qRegisterMetaType(); QSignalSpy spy(&loader, SIGNAL(effectLoaded(KWin::Effect*,QString))); // connect to signal to ensure that we delete the Effect again as the Effect doesn't have a parent connect(&loader, &KWin::PluginEffectLoader::effectLoaded, [&name](KWin::Effect *effect, const QString &effectName) { QCOMPARE(effectName, name.toLower()); effect->deleteLater(); } ); // try to load the Effect QCOMPARE(loader.loadEffect(name), expected); // loading again should fail QVERIFY(!loader.loadEffect(name)); // signal spy should have got the signal if it was expected QCOMPARE(spy.isEmpty(), !expected); if (!spy.isEmpty()) { QCOMPARE(spy.count(), 1); // if we caught a signal it should have the effect name we passed in QList arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name.toLower()); } spy.clear(); QVERIFY(spy.isEmpty()); // now if we wait for the events being processed, the effect will get deleted and it should load again QTest::qWait(1); QCOMPARE(loader.loadEffect(name), expected); // signal spy should have got the signal if it was expected QCOMPARE(spy.isEmpty(), !expected); if (!spy.isEmpty()) { QCOMPARE(spy.count(), 1); // if we caught a signal it should have the effect name we passed in QList arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name.toLower()); } } void TestPluginEffectLoader::testLoadPluginEffect_data() { QTest::addColumn("name"); QTest::addColumn("expected"); QTest::addColumn("type"); QTest::addColumn("loadFlags"); QTest::addColumn("enabledByDefault"); const KWin::CompositingType xc = KWin::XRenderCompositing; const KWin::CompositingType oc = KWin::OpenGL2Compositing; const KWin::LoadEffectFlags checkDefault = KWin::LoadEffectFlag::Load | KWin::LoadEffectFlag::CheckDefaultFunction; const KWin::LoadEffectFlags forceFlags = KWin::LoadEffectFlag::Load; const KWin::LoadEffectFlags dontLoadFlags = KWin::LoadEffectFlags(); // enabled by default, but not supported QTest::newRow("fakeeffectplugin") << QStringLiteral("fakeeffectplugin") << false << xc << checkDefault << false; // enabled by default, check default false QTest::newRow("supported, check default error") << QStringLiteral("fakeeffectplugin") << false << oc << checkDefault << false; // enabled by default, check default true QTest::newRow("supported, check default") << QStringLiteral("fakeeffectplugin") << true << oc << checkDefault << true; // enabled by default, check default false QTest::newRow("supported, check default error, forced") << QStringLiteral("fakeeffectplugin") << true << oc << forceFlags << false; // enabled by default, check default true QTest::newRow("supported, check default, don't load") << QStringLiteral("fakeeffectplugin") << false << oc << dontLoadFlags << true; // incorrect version QTest::newRow("Version") << QStringLiteral("effectversion") << false << xc << forceFlags << true; } void TestPluginEffectLoader::testLoadPluginEffect() { QFETCH(QString, name); QFETCH(bool, expected); QFETCH(KWin::CompositingType, type); QFETCH(KWin::LoadEffectFlags, loadFlags); QFETCH(bool, enabledByDefault); MockEffectsHandler mockHandler(type); mockHandler.setProperty("testEnabledByDefault", enabledByDefault); KWin::PluginEffectLoader loader; loader.setPluginSubDirectory(QString()); KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); loader.setConfig(config); const auto plugins = KPluginLoader::findPlugins(QString(), [name] (const KPluginMetaData &data) { return data.pluginId().compare(name, Qt::CaseInsensitive) == 0 && data.serviceTypes().contains(QStringLiteral("KWin/Effect")); } ); QCOMPARE(plugins.size(), 1); qRegisterMetaType(); QSignalSpy spy(&loader, SIGNAL(effectLoaded(KWin::Effect*,QString))); // connect to signal to ensure that we delete the Effect again as the Effect doesn't have a parent connect(&loader, &KWin::PluginEffectLoader::effectLoaded, [&name](KWin::Effect *effect, const QString &effectName) { QCOMPARE(effectName, name); effect->deleteLater(); } ); // try to load the Effect QCOMPARE(loader.loadEffect(plugins.first(), loadFlags), expected); // loading again should fail QVERIFY(!loader.loadEffect(plugins.first(), loadFlags)); // signal spy should have got the signal if it was expected QCOMPARE(spy.isEmpty(), !expected); if (!spy.isEmpty()) { QCOMPARE(spy.count(), 1); // if we caught a signal it should have the effect name we passed in QList arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name); } spy.clear(); QVERIFY(spy.isEmpty()); // now if we wait for the events being processed, the effect will get deleted and it should load again QTest::qWait(1); QCOMPARE(loader.loadEffect(plugins.first(), loadFlags), expected); // signal spy should have got the signal if it was expected QCOMPARE(spy.isEmpty(), !expected); if (!spy.isEmpty()) { QCOMPARE(spy.count(), 1); // if we caught a signal it should have the effect name we passed in QList arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name); } } void TestPluginEffectLoader::testLoadAllEffects() { MockEffectsHandler mockHandler(KWin::OpenGL2Compositing); mockHandler.setProperty("testEnabledByDefault", true); KWin::PluginEffectLoader loader; loader.setPluginSubDirectory(QString()); KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); // prepare the configuration to hard enable/disable the effects we want to load KConfigGroup plugins = config->group("Plugins"); plugins.writeEntry(QStringLiteral("fakeeffectpluginEnabled"), false); plugins.sync(); loader.setConfig(config); qRegisterMetaType(); QSignalSpy spy(&loader, SIGNAL(effectLoaded(KWin::Effect*,QString))); // connect to signal to ensure that we delete the Effect again as the Effect doesn't have a parent connect(&loader, &KWin::PluginEffectLoader::effectLoaded, [](KWin::Effect *effect) { effect->deleteLater(); } ); // the config is prepared so that no Effect gets loaded! loader.queryAndLoadAll(); // we need to wait some time because it's queued and in a thread QVERIFY(!spy.wait(100)); // now let's prepare a config which has one effect explicitly enabled plugins.writeEntry(QStringLiteral("fakeeffectpluginEnabled"), true); plugins.sync(); loader.queryAndLoadAll(); // should load one effect in first go QVERIFY(spy.wait(100)); // and afterwards it should not load another one QVERIFY(!spy.wait(10)); QCOMPARE(spy.size(), 1); // if we caught a signal it should have the effect name we passed in QList arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), QStringLiteral("fakeeffectplugin")); spy.clear(); } void TestPluginEffectLoader::testCancelLoadAllEffects() { // this test verifies that no test gets loaded when the loader gets cleared MockEffectsHandler mockHandler(KWin::OpenGL2Compositing); KWin::PluginEffectLoader loader; loader.setPluginSubDirectory(QString()); // prepare the configuration to hard enable/disable the effects we want to load KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); KConfigGroup plugins = config->group("Plugins"); plugins.writeEntry(QStringLiteral("fakeeffectpluginEnabled"), true); plugins.sync(); loader.setConfig(config); qRegisterMetaType(); QSignalSpy spy(&loader, &KWin::PluginEffectLoader::effectLoaded); QVERIFY(spy.isValid()); loader.queryAndLoadAll(); loader.clear(); // Should not load any effect QVERIFY(!spy.wait(100)); QVERIFY(spy.isEmpty()); } QTEST_MAIN(TestPluginEffectLoader) #include "test_plugin_effectloader.moc" diff --git a/autotests/test_scripted_effectloader.cpp b/autotests/test_scripted_effectloader.cpp index 16e970b53..c7aef31c7 100644 --- a/autotests/test_scripted_effectloader.cpp +++ b/autotests/test_scripted_effectloader.cpp @@ -1,454 +1,450 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2014 Martin Gräßlin 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 "../effectloader.h" #include "mock_effectshandler.h" #include "../scripting/scriptedeffect.h" // for mocking #include "../cursor.h" #include "../input.h" #include "../screenedge.h" // KDE #include #include #include // Qt #include #include Q_DECLARE_METATYPE(KWin::LoadEffectFlag) Q_DECLARE_METATYPE(KWin::LoadEffectFlags) Q_DECLARE_METATYPE(KWin::Effect*) Q_DECLARE_METATYPE(KSharedConfigPtr) Q_LOGGING_CATEGORY(KWIN_CORE, "kwin_core") namespace KWin { ScreenEdges *ScreenEdges::s_self = nullptr; void ScreenEdges::reserve(ElectricBorder, QObject *, const char *) { } void ScreenEdges::reserveTouch(ElectricBorder, QAction *) { } InputRedirection *InputRedirection::s_self = nullptr; void InputRedirection::registerShortcut(const QKeySequence &, QAction *) { } namespace MetaScripting { void registration(QScriptEngine *) { } } static QPoint s_cursorPos = QPoint(); QPoint Cursor::pos() { return s_cursorPos; } } class TestScriptedEffectLoader : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void testHasEffect_data(); void testHasEffect(); void testKnownEffects(); void testLoadEffect_data(); void testLoadEffect(); void testLoadScriptedEffect_data(); void testLoadScriptedEffect(); void testLoadAllEffects(); void testCancelLoadAllEffects(); }; void TestScriptedEffectLoader::initTestCase() { auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); QCoreApplication::instance()->setProperty("config", QVariant::fromValue(config)); } void TestScriptedEffectLoader::testHasEffect_data() { QTest::addColumn("name"); QTest::addColumn("expected"); // all the built-in effects should fail QTest::newRow("blur") << QStringLiteral("blur") << false; QTest::newRow("Colorpicker") << QStringLiteral("colorpicker") << false; QTest::newRow("Contrast") << QStringLiteral("contrast") << false; QTest::newRow("CoverSwitch") << QStringLiteral("coverswitch") << false; QTest::newRow("Cube") << QStringLiteral("cube") << false; QTest::newRow("CubeSlide") << QStringLiteral("cubeslide") << false; QTest::newRow("DesktopGrid") << QStringLiteral("desktopgrid") << false; QTest::newRow("DimInactive") << QStringLiteral("diminactive") << false; QTest::newRow("DimScreen") << QStringLiteral("dimscreen") << false; QTest::newRow("FallApart") << QStringLiteral("fallapart") << false; QTest::newRow("FlipSwitch") << QStringLiteral("flipswitch") << false; QTest::newRow("Glide") << QStringLiteral("glide") << false; QTest::newRow("HighlightWindow") << QStringLiteral("highlightwindow") << false; QTest::newRow("Invert") << QStringLiteral("invert") << false; QTest::newRow("Kscreen") << QStringLiteral("kscreen") << false; QTest::newRow("Logout") << QStringLiteral("logout") << false; QTest::newRow("LookingGlass") << QStringLiteral("lookingglass") << false; QTest::newRow("MagicLamp") << QStringLiteral("magiclamp") << false; QTest::newRow("Magnifier") << QStringLiteral("magnifier") << false; QTest::newRow("MinimizeAnimation") << QStringLiteral("minimizeanimation") << false; QTest::newRow("MouseClick") << QStringLiteral("mouseclick") << false; QTest::newRow("MouseMark") << QStringLiteral("mousemark") << false; QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << false; QTest::newRow("Resize") << QStringLiteral("resize") << false; QTest::newRow("Scale") << QStringLiteral("scale") << false; QTest::newRow("ScreenEdge") << QStringLiteral("screenedge") << false; QTest::newRow("ScreenShot") << QStringLiteral("screenshot") << false; QTest::newRow("Sheet") << QStringLiteral("sheet") << false; QTest::newRow("ShowFps") << QStringLiteral("showfps") << false; QTest::newRow("ShowPaint") << QStringLiteral("showpaint") << false; QTest::newRow("Slide") << QStringLiteral("slide") << false; QTest::newRow("SlideBack") << QStringLiteral("slideback") << false; QTest::newRow("SlidingPopups") << QStringLiteral("slidingpopups") << false; QTest::newRow("SnapHelper") << QStringLiteral("snaphelper") << false; QTest::newRow("StartupFeedback") << QStringLiteral("startupfeedback") << false; QTest::newRow("ThumbnailAside") << QStringLiteral("thumbnailaside") << false; QTest::newRow("TrackMouse") << QStringLiteral("trackmouse") << false; QTest::newRow("WindowGeometry") << QStringLiteral("windowgeometry") << false; QTest::newRow("WobblyWindows") << QStringLiteral("wobblywindows") << false; QTest::newRow("Zoom") << QStringLiteral("zoom") << false; QTest::newRow("Non Existing") << QStringLiteral("InvalidName") << false; QTest::newRow("Fade - without kwin4_effect") << QStringLiteral("fade") << false; QTest::newRow("Fade + kwin4_effect") << QStringLiteral("kwin4_effect_fade") << true; QTest::newRow("Fade + kwin4_effect + CS") << QStringLiteral("kwin4_eFfect_fAde") << true; QTest::newRow("FadeDesktop") << QStringLiteral("kwin4_effect_fadedesktop") << true; QTest::newRow("FrozenApp") << QStringLiteral("kwin4_effect_frozenapp") << true; QTest::newRow("DialogParent") << QStringLiteral("kwin4_effect_dialogparent") << true; QTest::newRow("Login") << QStringLiteral("kwin4_effect_login") << true; QTest::newRow("Logout") << QStringLiteral("kwin4_effect_logout") << true; QTest::newRow("Maximize") << QStringLiteral("kwin4_effect_maximize") << true; - QTest::newRow("ScaleIn") << QStringLiteral("kwin4_effect_scalein") << true; QTest::newRow("Translucency") << QStringLiteral("kwin4_effect_translucency") << true; } void TestScriptedEffectLoader::testHasEffect() { QFETCH(QString, name); QFETCH(bool, expected); MockEffectsHandler mockHandler(KWin::XRenderCompositing); KWin::ScriptedEffectLoader loader; QCOMPARE(loader.hasEffect(name), expected); // each available effect should also be supported QCOMPARE(loader.isEffectSupported(name), expected); if (expected) { mockHandler.setAnimationsSupported(false); QVERIFY(!loader.isEffectSupported(name)); } } void TestScriptedEffectLoader::testKnownEffects() { QStringList expectedEffects; expectedEffects << QStringLiteral("kwin4_effect_dialogparent") << QStringLiteral("kwin4_effect_fade") << QStringLiteral("kwin4_effect_fadedesktop") << QStringLiteral("kwin4_effect_frozenapp") << QStringLiteral("kwin4_effect_login") << QStringLiteral("kwin4_effect_logout") << QStringLiteral("kwin4_effect_maximize") - << QStringLiteral("kwin4_effect_scalein") << QStringLiteral("kwin4_effect_translucency"); KWin::ScriptedEffectLoader loader; QStringList result = loader.listOfKnownEffects(); // at least as many effects as we expect - system running the test could have more effects QVERIFY(result.size() >= expectedEffects.size()); for (const QString &effect : expectedEffects) { QVERIFY(result.contains(effect)); } } void TestScriptedEffectLoader::testLoadEffect_data() { QTest::addColumn("name"); QTest::addColumn("expected"); QTest::newRow("Non Existing") << QStringLiteral("InvalidName") << false; QTest::newRow("Fade - without kwin4_effect") << QStringLiteral("fade") << false; QTest::newRow("Fade + kwin4_effect") << QStringLiteral("kwin4_effect_fade") << true; QTest::newRow("Fade + kwin4_effect + CS") << QStringLiteral("kwin4_eFfect_fAde") << true; QTest::newRow("FadeDesktop") << QStringLiteral("kwin4_effect_fadedesktop") << true; QTest::newRow("FrozenApp") << QStringLiteral("kwin4_effect_frozenapp") << true; QTest::newRow("DialogParent") << QStringLiteral("kwin4_effect_dialogparent") << true; QTest::newRow("Login") << QStringLiteral("kwin4_effect_login") << true; QTest::newRow("Logout") << QStringLiteral("kwin4_effect_logout") << true; QTest::newRow("Maximize") << QStringLiteral("kwin4_effect_maximize") << true; - QTest::newRow("ScaleIn") << QStringLiteral("kwin4_effect_scalein") << true; QTest::newRow("Translucency") << QStringLiteral("kwin4_effect_translucency") << true; } void TestScriptedEffectLoader::testLoadEffect() { QFETCH(QString, name); QFETCH(bool, expected); MockEffectsHandler mockHandler(KWin::XRenderCompositing); KWin::ScriptedEffectLoader loader; KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); loader.setConfig(config); qRegisterMetaType(); QSignalSpy spy(&loader, SIGNAL(effectLoaded(KWin::Effect*,QString))); // connect to signal to ensure that we delete the Effect again as the Effect doesn't have a parent connect(&loader, &KWin::ScriptedEffectLoader::effectLoaded, [&name](KWin::Effect *effect, const QString &effectName) { QCOMPARE(effectName, name.toLower()); effect->deleteLater(); } ); // try to load the Effect QCOMPARE(loader.loadEffect(name), expected); // loading again should fail QVERIFY(!loader.loadEffect(name)); // signal spy should have got the signal if it was expected QCOMPARE(spy.isEmpty(), !expected); if (!spy.isEmpty()) { QCOMPARE(spy.count(), 1); // if we caught a signal it should have the effect name we passed in QList arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name.toLower()); } spy.clear(); QVERIFY(spy.isEmpty()); // now if we wait for the events being processed, the effect will get deleted and it should load again QTest::qWait(1); QCOMPARE(loader.loadEffect(name), expected); // signal spy should have got the signal if it was expected QCOMPARE(spy.isEmpty(), !expected); if (!spy.isEmpty()) { QCOMPARE(spy.count(), 1); // if we caught a signal it should have the effect name we passed in QList arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name.toLower()); } } void TestScriptedEffectLoader::testLoadScriptedEffect_data() { QTest::addColumn("name"); QTest::addColumn("expected"); QTest::addColumn("loadFlags"); const KWin::LoadEffectFlags checkDefault = KWin::LoadEffectFlag::Load | KWin::LoadEffectFlag::CheckDefaultFunction; const KWin::LoadEffectFlags forceFlags = KWin::LoadEffectFlag::Load; const KWin::LoadEffectFlags dontLoadFlags = KWin::LoadEffectFlags(); // enabled by default - QTest::newRow("Fade") << QStringLiteral("kwin4_effect_fade") << true << checkDefault; + QTest::newRow("Fade") << QStringLiteral("kwin4_effect_fade") << true << checkDefault; // not enabled by default - QTest::newRow("Scalein") << QStringLiteral("kwin4_effect_scalein") << true << checkDefault; + QTest::newRow("EyeOnScreen") << QStringLiteral("kwin4_effect_eyeonscreen") << true << checkDefault; // Force an Effect which will load - QTest::newRow("Scalein-Force") << QStringLiteral("kwin4_effect_scalein") << true << forceFlags; + QTest::newRow("EyeOnScreen-Force") << QStringLiteral("kwin4_effect_eyeonscreen") << true << forceFlags; // Enforce no load of effect which is enabled by default - QTest::newRow("Fade-DontLoad") << QStringLiteral("kwin4_effect_fade") << false << dontLoadFlags; + QTest::newRow("Fade-DontLoad") << QStringLiteral("kwin4_effect_fade") << false << dontLoadFlags; // Enforce no load of effect which is not enabled by default, but enforced - QTest::newRow("Scalein-DontLoad") << QStringLiteral("kwin4_effect_scalein") << false << dontLoadFlags; + QTest::newRow("EyeOnScreen-DontLoad") << QStringLiteral("kwin4_effect_eyeonscreen") << false << dontLoadFlags; } void TestScriptedEffectLoader::testLoadScriptedEffect() { QFETCH(QString, name); QFETCH(bool, expected); QFETCH(KWin::LoadEffectFlags, loadFlags); MockEffectsHandler mockHandler(KWin::XRenderCompositing); KWin::ScriptedEffectLoader loader; KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); loader.setConfig(config); const auto services = KPackage::PackageLoader::self()->findPackages(QStringLiteral("KWin/Effect"), QStringLiteral("kwin/effects"), [name] (const KPluginMetaData &metadata) { return metadata.pluginId().compare(name, Qt::CaseInsensitive) == 0; } ); QCOMPARE(services.count(), 1); qRegisterMetaType(); QSignalSpy spy(&loader, SIGNAL(effectLoaded(KWin::Effect*,QString))); // connect to signal to ensure that we delete the Effect again as the Effect doesn't have a parent connect(&loader, &KWin::ScriptedEffectLoader::effectLoaded, [&name](KWin::Effect *effect, const QString &effectName) { QCOMPARE(effectName, name.toLower()); effect->deleteLater(); } ); // try to load the Effect QCOMPARE(loader.loadEffect(services.first(), loadFlags), expected); // loading again should fail QVERIFY(!loader.loadEffect(services.first(), loadFlags)); // signal spy should have got the signal if it was expected QCOMPARE(spy.isEmpty(), !expected); if (!spy.isEmpty()) { QCOMPARE(spy.count(), 1); // if we caught a signal it should have the effect name we passed in QList arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name.toLower()); } spy.clear(); QVERIFY(spy.isEmpty()); // now if we wait for the events being processed, the effect will get deleted and it should load again QTest::qWait(1); QCOMPARE(loader.loadEffect(services.first(), loadFlags), expected); // signal spy should have got the signal if it was expected QCOMPARE(spy.isEmpty(), !expected); if (!spy.isEmpty()) { QCOMPARE(spy.count(), 1); // if we caught a signal it should have the effect name we passed in QList arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name.toLower()); } } void TestScriptedEffectLoader::testLoadAllEffects() { MockEffectsHandler mockHandler(KWin::XRenderCompositing); KWin::ScriptedEffectLoader loader; KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); const QString kwin4 = QStringLiteral("kwin4_effect_"); // prepare the configuration to hard enable/disable the effects we want to load KConfigGroup plugins = config->group("Plugins"); plugins.writeEntry(kwin4 + QStringLiteral("dialogparentEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("fadeEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("fadedesktopEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("frozenappEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("loginEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("logoutEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("maximizeEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("minimizeanimationEnabled"), false); - plugins.writeEntry(kwin4 + QStringLiteral("scaleinEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("translucencyEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("eyeonscreenEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("windowapertureEnabled"), false); plugins.writeEntry(kwin4 + QStringLiteral("morphingpopupsEnabled"), false); plugins.sync(); loader.setConfig(config); qRegisterMetaType(); QSignalSpy spy(&loader, SIGNAL(effectLoaded(KWin::Effect*,QString))); // connect to signal to ensure that we delete the Effect again as the Effect doesn't have a parent connect(&loader, &KWin::ScriptedEffectLoader::effectLoaded, [](KWin::Effect *effect) { effect->deleteLater(); } ); // the config is prepared so that no Effect gets loaded! loader.queryAndLoadAll(); // we need to wait some time because it's queued and in a thread QVERIFY(!spy.wait(100)); // now let's prepare a config which has one effect explicitly enabled - plugins.writeEntry(kwin4 + QStringLiteral("scaleinEnabled"), true); + plugins.writeEntry(kwin4 + QStringLiteral("eyeonscreenEnabled"), true); plugins.sync(); loader.queryAndLoadAll(); // should load one effect in first go QVERIFY(spy.wait(100)); // and afterwards it should not load another one QVERIFY(!spy.wait(10)); QCOMPARE(spy.size(), 1); // if we caught a signal it should have the effect name we passed in QList arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); - QCOMPARE(arguments.at(1).toString(), kwin4 + QStringLiteral("scalein")); + QCOMPARE(arguments.at(1).toString(), kwin4 + QStringLiteral("eyeonscreen")); spy.clear(); // let's delete one of the default entries plugins.deleteEntry(kwin4 + QStringLiteral("fadeEnabled")); plugins.sync(); QVERIFY(spy.isEmpty()); loader.queryAndLoadAll(); // let's use qWait as we need to wait for two signals to be emitted QTRY_COMPARE(spy.size(), 2); QStringList loadedEffects; for (auto &list : spy) { QCOMPARE(list.size(), 2); loadedEffects << list.at(1).toString(); } qSort(loadedEffects); - QCOMPARE(loadedEffects.at(0), kwin4 + QStringLiteral("fade")); - QCOMPARE(loadedEffects.at(1), kwin4 + QStringLiteral("scalein")); + QCOMPARE(loadedEffects.at(0), kwin4 + QStringLiteral("eyeonscreen")); + QCOMPARE(loadedEffects.at(1), kwin4 + QStringLiteral("fade")); } void TestScriptedEffectLoader::testCancelLoadAllEffects() { // this test verifies that no test gets loaded when the loader gets cleared MockEffectsHandler mockHandler(KWin::XRenderCompositing); KWin::ScriptedEffectLoader loader; // prepare the configuration to hard enable/disable the effects we want to load KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); const QString kwin4 = QStringLiteral("kwin4_effect_"); KConfigGroup plugins = config->group("Plugins"); - plugins.writeEntry(kwin4 + QStringLiteral("scaleinEnabled"), true); + plugins.writeEntry(kwin4 + QStringLiteral("eyeonscreenEnabled"), true); plugins.sync(); loader.setConfig(config); qRegisterMetaType(); QSignalSpy spy(&loader, &KWin::ScriptedEffectLoader::effectLoaded); QVERIFY(spy.isValid()); loader.queryAndLoadAll(); loader.clear(); // Should not load any effect QVERIFY(!spy.wait(100)); QVERIFY(spy.isEmpty()); } QTEST_MAIN(TestScriptedEffectLoader) #include "test_scripted_effectloader.moc" diff --git a/effects/CMakeLists.txt b/effects/CMakeLists.txt index 71e011e77..06445ccb5 100644 --- a/effects/CMakeLists.txt +++ b/effects/CMakeLists.txt @@ -1,195 +1,194 @@ # KI18N Translation Domain for this library add_definitions(-DTRANSLATION_DOMAIN=\"kwin_effects\" -DEFFECT_BUILTINS) include_directories(${KWIN_SOURCE_DIR}) # for xcbutils.h set(kwin_effect_OWN_LIBS kwineffects ) if( KWIN_HAVE_XRENDER_COMPOSITING ) set(kwin_effect_OWN_LIBS ${kwin_effect_OWN_LIBS} kwinxrenderutils) endif() set(kwin_effect_KDE_LIBS KF5::ConfigGui KF5::ConfigWidgets KF5::GlobalAccel KF5::I18n KF5::WindowSystem KF5::Plasma # screenedge effect KF5::IconThemes KF5::Service KF5::Notifications # screenshot effect ) set(kwin_effect_QT_LIBS Qt5::Concurrent Qt5::DBus Qt5::Quick Qt5::X11Extras ) set(kwin_effect_XLIB_LIBS ${X11_X11_LIB} ) set(kwin_effect_XCB_LIBS XCB::XCB XCB::IMAGE XCB::XFIXES ) if( KWIN_HAVE_XRENDER_COMPOSITING ) set(kwin_effect_XCB_LIBS ${kwin_effect_XCB_LIBS} XCB::RENDER) endif() set(kwin_effect_OWN_LIBS ${kwin_effect_OWN_LIBS} kwinglutils) macro( KWIN4_ADD_EFFECT_BACKEND name ) add_library( ${name} SHARED ${ARGN} ) target_link_libraries( ${name} PRIVATE ${kwin_effect_OWN_LIBS} ${kwin_effect_KDE_LIBS} ${kwin_effect_QT_LIBS} ${kwin_effect_XLIB_LIBS} ${kwin_effect_XCB_LIBS}) endmacro() # Adds effect plugin with given name. Sources are given after the name macro( KWIN4_ADD_EFFECT name ) kwin4_add_effect_backend(kwin4_effect_${name} ${ARGN}) set_target_properties(kwin4_effect_${name} PROPERTIES VERSION 1.0.0 SOVERSION 1 ) set_target_properties(kwin4_effect_${name} PROPERTIES OUTPUT_NAME ${KWIN_NAME}4_effect_${name}) install(TARGETS kwin4_effect_${name} ${INSTALL_TARGETS_DEFAULT_ARGS} ) endmacro() # Install the KWin/Effect service type install( FILES kwineffect.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR} ) # Create initial variables set( kwin4_effect_include_directories ) set( kwin4_effect_builtins_sources logging.cpp effect_builtins.cpp blur/blur.cpp blur/blurshader.cpp colorpicker/colorpicker.cpp cube/cube.cpp cube/cube_proxy.cpp cube/cubeslide.cpp coverswitch/coverswitch.cpp desktopgrid/desktopgrid.cpp diminactive/diminactive.cpp flipswitch/flipswitch.cpp glide/glide.cpp invert/invert.cpp lookingglass/lookingglass.cpp magiclamp/magiclamp.cpp magnifier/magnifier.cpp mouseclick/mouseclick.cpp mousemark/mousemark.cpp presentwindows/presentwindows.cpp presentwindows/presentwindows_proxy.cpp resize/resize.cpp scale/scale.cpp showfps/showfps.cpp slide/slide.cpp thumbnailaside/thumbnailaside.cpp touchpoints/touchpoints.cpp trackmouse/trackmouse.cpp windowgeometry/windowgeometry.cpp wobblywindows/wobblywindows.cpp zoom/zoom.cpp ) qt5_add_resources( kwin4_effect_builtins_sources shaders.qrc ) kconfig_add_kcfg_files(kwin4_effect_builtins_sources blur/blurconfig.kcfgc cube/cubeslideconfig.kcfgc cube/cubeconfig.kcfgc coverswitch/coverswitchconfig.kcfgc desktopgrid/desktopgridconfig.kcfgc diminactive/diminactiveconfig.kcfgc fallapart/fallapartconfig.kcfgc flipswitch/flipswitchconfig.kcfgc glide/glideconfig.kcfgc lookingglass/lookingglassconfig.kcfgc magiclamp/magiclampconfig.kcfgc magnifier/magnifierconfig.kcfgc mouseclick/mouseclickconfig.kcfgc mousemark/mousemarkconfig.kcfgc presentwindows/presentwindowsconfig.kcfgc resize/resizeconfig.kcfgc scale/scaleconfig.kcfgc showfps/showfpsconfig.kcfgc slide/slideconfig.kcfgc slidingpopups/slidingpopupsconfig.kcfgc thumbnailaside/thumbnailasideconfig.kcfgc trackmouse/trackmouseconfig.kcfgc windowgeometry/windowgeometryconfig.kcfgc wobblywindows/wobblywindowsconfig.kcfgc zoom/zoomconfig.kcfgc ) # scripted effects add_subdirectory( dialogparent ) add_subdirectory( eyeonscreen ) add_subdirectory( fade ) add_subdirectory( fadedesktop ) add_subdirectory( frozenapp ) add_subdirectory( login ) add_subdirectory( logout ) add_subdirectory( maximize ) add_subdirectory( morphingpopups ) -add_subdirectory( scalein ) add_subdirectory( translucency ) add_subdirectory( windowaperture ) ############################################################################### # Built-in effects go here # Common effects add_subdirectory( desktopgrid ) add_subdirectory( diminactive ) include( dimscreen/CMakeLists.txt ) include( fallapart/CMakeLists.txt ) include( highlightwindow/CMakeLists.txt ) include( kscreen/CMakeLists.txt ) add_subdirectory( magiclamp ) include( minimizeanimation/CMakeLists.txt ) add_subdirectory( presentwindows ) add_subdirectory( resize ) include( screenedge/CMakeLists.txt ) add_subdirectory( showfps ) include( showpaint/CMakeLists.txt ) add_subdirectory( slide ) include( slideback/CMakeLists.txt ) include( slidingpopups/CMakeLists.txt ) add_subdirectory( thumbnailaside ) add_subdirectory( windowgeometry ) add_subdirectory( zoom ) # OpenGL-specific effects add_subdirectory( blur ) include( backgroundcontrast/CMakeLists.txt ) add_subdirectory( coverswitch ) add_subdirectory( cube ) add_subdirectory( flipswitch ) add_subdirectory( glide ) add_subdirectory( invert ) add_subdirectory( lookingglass ) add_subdirectory( magnifier ) add_subdirectory( mouseclick ) add_subdirectory( mousemark ) add_subdirectory( scale ) include( screenshot/CMakeLists.txt ) include( sheet/CMakeLists.txt ) include( snaphelper/CMakeLists.txt ) include( startupfeedback/CMakeLists.txt ) add_subdirectory( trackmouse ) add_subdirectory( wobblywindows ) ############################################################################### # Add the builtins plugin kwin4_add_effect( builtins ${kwin4_effect_builtins_sources} ) diff --git a/effects/scalein/CMakeLists.txt b/effects/scalein/CMakeLists.txt deleted file mode 100644 index 28f40b337..000000000 --- a/effects/scalein/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory( package ) diff --git a/effects/scalein/package/CMakeLists.txt b/effects/scalein/package/CMakeLists.txt deleted file mode 100644 index 3b37218c6..000000000 --- a/effects/scalein/package/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -install(DIRECTORY contents DESTINATION ${DATA_INSTALL_DIR}/${KWIN_NAME}/effects/kwin4_effect_scalein) -install(FILES metadata.desktop DESTINATION ${DATA_INSTALL_DIR}/${KWIN_NAME}/effects/kwin4_effect_scalein) - -install(FILES metadata.desktop - DESTINATION ${SERVICES_INSTALL_DIR}/${KWIN_NAME} - RENAME kwin4_effect_scalein.desktop) diff --git a/effects/scalein/package/contents/code/main.js b/effects/scalein/package/contents/code/main.js deleted file mode 100644 index 596118385..000000000 --- a/effects/scalein/package/contents/code/main.js +++ /dev/null @@ -1,77 +0,0 @@ -/******************************************************************** - KWin - the KDE window manager - This file is part of the KDE project. - - Copyright (C) 2013 Kai Uwe Broulik - -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 . -*********************************************************************/ -/*global effect, effects, animate, animationTime, Effect, QEasingCurve */ -var scaleInEffect = { - duration: animationTime(150), - loadConfig: function () { - "use strict"; - scaleInEffect.duration = animationTime(150); - }, - isScaleWindow: function (window) { - "use strict"; - if (window.popupMenu || window.specialWindow || window.utility || window.minimized || - effect.isGrabbed(window, Effect.WindowAddedGrabRole)) { - return false; - } - return true; - }, - scaleIn: function (window) { - "use strict"; - window.scaleInWindowTypeAnimation = animate({ - window: window, - duration: scaleInEffect.duration, - curve: QEasingCurve.InOutQuad, - animations: [{ - type: Effect.Opacity, - from: 0.0, - to: 1.0 - }, { - type: Effect.Scale, - from: 0.75, - to: 1.0 - }] - }); - }, - added: function (window) { - "use strict"; - if (!scaleInEffect.isScaleWindow(window)) { - return; - } - scaleInEffect.scaleIn(window); - }, - dataChanged: function (window, role) { - "use strict"; - if (role == Effect.WindowAddedGrabRole) { - if (effect.isGrabbed(window, Effect.WindowAddedGrabRole)) { - if (window.scaleInWindowTypeAnimation !== undefined) { - cancel(window.scaleInWindowTypeAnimation); - window.scaleInWindowTypeAnimation = undefined; - } - } - } - }, - init: function () { - "use strict"; - effect.configChanged.connect(scaleInEffect.loadConfig); - effects.windowAdded.connect(scaleInEffect.added); - effects.windowDataChanged.connect(scaleInEffect.dataChanged); - } -}; -scaleInEffect.init(); diff --git a/effects/scalein/package/metadata.desktop b/effects/scalein/package/metadata.desktop deleted file mode 100644 index 1dda72cc1..000000000 --- a/effects/scalein/package/metadata.desktop +++ /dev/null @@ -1,163 +0,0 @@ -[Desktop Entry] -Name=Scale In -Name[af]=Rek-verskyn -Name[ar]=تحجيم النوافذ -Name[bg]=Увеличаване -Name[bs]=Uvećana razmjera -Name[ca]=Escalat -Name[ca@valencia]=Escalat -Name[cs]=Zvětšení -Name[csb]=Skalowanié -Name[da]=Skalér ind -Name[de]=Hineinzoomen -Name[el]=Εστίαση -Name[en_GB]=Scale In -Name[eo]=Enskali -Name[es]=Escalar -Name[et]=Skaleerimine -Name[eu]=Eskalatu -Name[fa]=مقیاس در -Name[fi]=Skaalaus -Name[fr]=Gradation -Name[fy]=Ynskale -Name[ga]=Scálaigh Isteach -Name[gl]=Ampliar -Name[gu]=અંદર આવવું -Name[he]=התקרבות -Name[hi]=स्केल इन -Name[hne]=स्केल इन -Name[hr]=Skaliranje -Name[hu]=Felbukkanás -Name[ia]=Scala intra -Name[id]=Scale In -Name[is]=Kvarða niður -Name[it]=Espandi -Name[ja]=スケールイン -Name[kk]=Масштабтау -Name[km]=ធ្វើ​មាត្រដ្ឋាន​ក្នុង -Name[kn]=ಸ್ಕೇಲ್ ಇನ್ -Name[ko]=확대 -Name[lt]=Išdidėjimas -Name[lv]=Mērogot iekšā -Name[mai]=स्केल इन -Name[mk]=Зголемување -Name[ml]=ആനുപാതികമാക്കുക -Name[mr]=लहान मोठे करा -Name[nb]=Skaler inn -Name[nds]=Inpassen -Name[ne]=भित्री मापन गर्नुहोस् -Name[nl]=Inschalen -Name[nn]=Skaler inn -Name[pa]=ਸਕੇਲ ਇਨ -Name[pl]=Skalowanie -Name[pt]=Escala -Name[pt_BR]=Dimensionar -Name[ro]=Scalează interior -Name[ru]=Анимация появления окна -Name[se]=Skálere sisa -Name[si]=ඇතුළට ප්‍රමාණිත කරන්න -Name[sk]=Škálovať -Name[sl]=Animirano pojavljanje -Name[sr]=Увећана размера -Name[sr@ijekavian]=Увећана размјера -Name[sr@ijekavianlatin]=Uvećana razmjera -Name[sr@latin]=Uvećana razmera -Name[sv]=Skala in -Name[ta]= காலியன் -Name[te]=స్కేల్ ఇన్ -Name[tg]=Масштабирование (увеличение) -Name[th]=ปรับขนาดขึ้น -Name[tr]=Açılan Pencereleri Canlandır -Name[ug]=يېقىنلاشتۇر -Name[uk]=Збільшення -Name[vi]=Co dãn vào -Name[wa]=Agrandi l' schåle -Name[x-test]=xxScale Inxx -Name[zh_CN]=拉近 -Name[zh_TW]=縮放 -Icon=preferences-system-windows-effect-scale-in -Comment=Animate the appearing of windows -Comment[ar]=يحرك عملية ظهور النوافذ -Comment[be@latin]=Animuje źjaŭleńnie akon. -Comment[bg]=Анимирано показване на прозорците -Comment[bs]=Animira pojavljivanje prozora -Comment[ca]=Anima l'aparició de les finestres -Comment[ca@valencia]=Anima l'aparició de les finestres -Comment[cs]=Animuje objevení oken -Comment[csb]=Animùjë pòkazëwanié sã òkna -Comment[da]=Animér vinduers fremkomst -Comment[de]=Animiert das Erscheinen von Fenstern. -Comment[el]=Εφέ κίνησης της εμφάνισης των παραθύρων -Comment[en_GB]=Animate the appearing of windows -Comment[eo]=Animigas la aperon de fenestroj -Comment[es]=Anima la aparición de ventanas -Comment[et]=Animeerib akende ilmumise -Comment[eu]=Leihoak agertzeko modua animatzen du -Comment[fi]=Animoi ikkunoiden ilmestymisen -Comment[fr]=Anime l'apparition des fenêtres -Comment[fy]=Bringt it ferskinen fan finsters ta libben -Comment[ga]=Déan beochan agus fuinneog á taispeáint -Comment[gl]=Anima a aparición das xanelas -Comment[gu]=વિન્ડોનો દેખાવ એનિમેટ કરો -Comment[he]=הנפשת ההופעה של חלונות -Comment[hi]=विंडो प्रकट होने को एनिमेट करता है -Comment[hne]=विंडो ल देखाय के बेरा मं एनीमेट करथे -Comment[hr]=Animacija pojavljivanja prozora -Comment[hu]=Animáció történik ablakok megjelenésekor -Comment[ia]=Anima le apparentia de fenestras -Comment[id]=Animasikan munculnya jendela -Comment[is]=Hreyfingaráhrif við birtingu glugga -Comment[it]=Anima l'apparizione delle finestre -Comment[ja]=ウィンドウの出現をアニメーション化します -Comment[kk]=Терезеледің пайда болуын анимациялау -Comment[km]=ធ្វើ​ឲ្យ​កា​របង្ហាញ​របស់​បង្អួច​មាន​ចលនា -Comment[kn]=ಕಿಟಕಿಗಳ ತೋರಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಸಜೀವನಗೊಳಿಸು -Comment[ko]=창이 등장하는 것을 애니메이션으로 보여 줍니다 -Comment[lt]=Animuoja langų atsiradimą -Comment[lv]=Animē logu parādīšanos -Comment[mk]=Го анимира појавувањето прозорци -Comment[ml]=ജാലകങ്ങള്‍ കളിച്ചുകൊണ്ടു് വരട്ടെ. -Comment[mr]=चौकट दर्शविणे एनीमेट करा -Comment[nb]=Animer vinduer som dukker opp -Comment[nds]=Dat Opduken vun Finstern animeren -Comment[nl]=Voorziet het verschijnen van vensters van een animatie -Comment[nn]=Animer opning av vindauge -Comment[pa]=ਵਿੰਡੋ ਵੇਖਾਉਣ ਨੂੰ ਐਨੀਮੇਟ ਕੀਤਾ ਜਾਂਦਾ ਹੈ -Comment[pl]=Efekt skalowania okien przy ich otwieraniu i zamykaniu -Comment[pt]=Animar a aparição das janelas -Comment[pt_BR]=Anima o aparecimento de janelas -Comment[ro]=Animează apariția ferestrelor -Comment[ru]=Анимация появления нового окна -Comment[si]=කවුළුවල දැක්වීම සජීවීකරණය කරන්න -Comment[sk]=Animuje objavenie okien -Comment[sl]=Pojavljanje oken je animirano -Comment[sr]=Анимира појављивање прозора -Comment[sr@ijekavian]=Анимира појављивање прозора -Comment[sr@ijekavianlatin]=Animira pojavljivanje prozora -Comment[sr@latin]=Animira pojavljivanje prozora -Comment[sv]=Animera när fönster framträder -Comment[ta]=Animate the appearing of windows -Comment[tg]=Анимация появления окон -Comment[th]=การปรากฎตัวของหน้าต่างในแบบเคลื่อนไหว -Comment[tr]=Pencerelerin açılışını canlandır -Comment[ug]=كۆزنەكلەرنىڭ ئېچىلىشىنى جانلاندۇر -Comment[uk]=Анімація появи вікон -Comment[vi]=Tạo hiệu ứng xuất hiện cửa sổ -Comment[wa]=Animer l' aparexhaedje des fniesses -Comment[x-test]=xxAnimate the appearing of windowsxx -Comment[zh_CN]=动画显示窗口的出现 -Comment[zh_TW]=動畫顯示視窗出現 - -Type=Service -X-Plasma-API=javascript -X-Plasma-MainScript=code/main.js -X-KDE-ServiceTypes=KWin/Effect -X-KDE-PluginInfo-Author=Luboš Luňák, Kai Uwe Broulik -X-KDE-PluginInfo-Email=l.lunak@kde.org, kde@privat.broulik.de -X-KDE-PluginInfo-Name=kwin4_effect_scalein -X-KDE-PluginInfo-Version=0.2.0 -X-KDE-PluginInfo-Category=Appearance -X-KDE-PluginInfo-Depends= -X-KDE-PluginInfo-License=GPL -X-KDE-PluginInfo-EnabledByDefault=false -X-KDE-Ordering=50 diff --git a/kconf_update/CMakeLists.txt b/kconf_update/CMakeLists.txt new file mode 100644 index 000000000..e20acaf0e --- /dev/null +++ b/kconf_update/CMakeLists.txt @@ -0,0 +1,2 @@ +install(FILES kwin.upd + DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR}) diff --git a/kconf_update/kwin.upd b/kconf_update/kwin.upd new file mode 100644 index 000000000..b179ca1f7 --- /dev/null +++ b/kconf_update/kwin.upd @@ -0,0 +1,7 @@ +Version=5 + +# Replace old Scale in effect with Scale effect. +Id=replace-scalein-with-scale +File=kwinrc +Group=Plugins +Key=kwin4_effect_scaleinEnabled,scaleEnabled