diff --git a/CMakeLists.txt b/CMakeLists.txt index a456a7935..54c90545a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,803 +1,808 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR) project(KWin) set(PROJECT_VERSION "5.19.80") set(PROJECT_VERSION_MAJOR 5) set(QT_MIN_VERSION "5.14.0") set(KF5_MIN_VERSION "5.70.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 Script Sensors 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(KDEClangFormat) include(ECMInstallIcons) include(ECMOptionalAddSubdirectory) add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0 -DQT_USE_QSTRINGBUILDER -DQT_NO_URL_CAST_FROM_STRING) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) 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 IconThemes IdleTime Notifications Package Plasma Wayland WidgetsAddons WindowSystem ) # required frameworks by config modules find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Completion Declarative KCMUtils KIO NewStuff Service TextWidgets 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(KF5Kirigami2 ${KF5_MIN_VERSION} CONFIG) set_package_properties(KF5Kirigami2 PROPERTIES DESCRIPTION "A QtQuick based components set" PURPOSE "Required at runtime for Virtual desktop KCM and the virtual keyboard" TYPE RUNTIME ) find_package(KDecoration2 5.18.0 CONFIG REQUIRED) find_package(KScreenLocker CONFIG REQUIRED) set_package_properties(KScreenLocker PROPERTIES TYPE REQUIRED PURPOSE "For screenlocker integration in kwin_wayland" ) find_package(KWaylandServer CONFIG REQUIRED) set_package_properties(KWaylandServer PROPERTIES TYPE REQUIRED PURPOSE "For Wayland integration" ) 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 "https://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 "https://www.freedesktop.org/wiki/Software/systemd/" 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 output of drm backend.") set(HAVE_GBM FALSE) if (HAVE_DRM AND gbm_FOUND) set(HAVE_GBM TRUE) endif() option(KWIN_BUILD_EGL_STREAM_BACKEND "Enable building of EGLStream based DRM backend" ON) if (HAVE_DRM AND KWIN_BUILD_EGL_STREAM_BACKEND) set(HAVE_EGL_STREAMS 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 "https://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 COMPOSITE CURSOR DAMAGE GLX ICCCM IMAGE KEYSYMS RANDR RENDER SHAPE SHM SYNC XCB XFIXES ) 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 "https://www.freetype.org" TYPE REQUIRED PURPOSE "Needed for KWin's QPA plugin." ) find_package(Fontconfig REQUIRED) set_package_properties(Fontconfig PROPERTIES TYPE REQUIRED PURPOSE "Needed for KWin's QPA plugin." ) find_package(Xwayland) set_package_properties(Xwayland PROPERTIES URL "https://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}) find_package(hwdata) set_package_properties(hwdata PROPERTIES TYPE RUNTIME PURPOSE "Runtime-only dependency needed for mapping monitor hardware vendor IDs to full names" URL "https://github.com/vcrhonek/hwdata" ) if(CMAKE_SYSTEM MATCHES "FreeBSD") find_package(epoll) set_package_properties(epoll PROPERTIES DESCRIPTION "I/O event notification facility" TYPE REQUIRED PURPOSE "Needed for running kwin_wayland" ) endif() 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") # 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) 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") configure_file(config-kwin.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kwin.h) ########### global ############### set(kwin_effects_dbus_xml ${CMAKE_CURRENT_SOURCE_DIR}/org.kde.kwin.Effects.xml) qt5_add_dbus_interface(effects_interface_SRCS ${kwin_effects_dbus_xml} kwineffects_interface) add_library(KWinEffectsInterface STATIC ${effects_interface_SRCS}) target_link_libraries(KWinEffectsInterface Qt5::DBus) 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_SRCS abstract_client.cpp abstract_opengl_context_attribute_builder.cpp abstract_output.cpp abstract_wayland_output.cpp activation.cpp appmenu.cpp atoms.cpp client_machine.cpp colorcorrection/clockskewnotifier.cpp colorcorrection/clockskewnotifierengine.cpp colorcorrection/colorcorrectdbusinterface.cpp colorcorrection/manager.cpp colorcorrection/suncalc.cpp composite.cpp cursor.cpp dbusinterface.cpp debug_console.cpp decorations/decoratedclient.cpp decorations/decorationbridge.cpp decorations/decorationpalette.cpp decorations/decorationrenderer.cpp decorations/decorations_logging.cpp decorations/settings.cpp deleted.cpp effectloader.cpp effects.cpp egl_context_attribute_builder.cpp events.cpp focuschain.cpp geometrytip.cpp gestures.cpp globalshortcuts.cpp group.cpp idle_inhibition.cpp input.cpp input_event.cpp input_event_spy.cpp internal_client.cpp keyboard_input.cpp keyboard_layout.cpp keyboard_layout_switching.cpp keyboard_repeat.cpp killwindow.cpp layers.cpp libinput/connection.cpp libinput/context.cpp libinput/device.cpp libinput/events.cpp libinput/libinput_logging.cpp linux_dmabuf.cpp logind.cpp main.cpp modifier_only_shortcuts.cpp moving_client_x11_filter.cpp netinfo.cpp onscreennotification.cpp options.cpp osd.cpp outline.cpp outputscreens.cpp overlaywindow.cpp placement.cpp platform.cpp pointer_input.cpp popup_input_filter.cpp rootinfo_filter.cpp rules.cpp rulebooksettings.cpp scene.cpp screenedge.cpp screenlockerwatcher.cpp screens.cpp scripting/dbuscall.cpp scripting/meta.cpp scripting/screenedgeitem.cpp scripting/scriptedeffect.cpp scripting/scripting.cpp scripting/scripting_logging.cpp scripting/scripting_model.cpp scripting/scriptingutils.cpp scripting/timer.cpp scripting/workspace_wrapper.cpp shadow.cpp sm.cpp subsurfacemonitor.cpp syncalarmx11filter.cpp thumbnailitem.cpp toplevel.cpp touch_hide_cursor_spy.cpp tablet_input.cpp touch_input.cpp udev.cpp unmanaged.cpp useractions.cpp utils.cpp virtualdesktops.cpp virtualdesktopsdbustypes.cpp virtualkeyboard.cpp virtualkeyboard_dbus.cpp was_user_interaction_x11_filter.cpp wayland_cursor_theme.cpp wayland_server.cpp window_property_notify_x11_filter.cpp workspace.cpp x11client.cpp x11eventfilter.cpp xcbutils.cpp xdgshellclient.cpp xkb.cpp xwaylandclient.cpp xwl/xwayland_interface.cpp ) if (CMAKE_SYSTEM_NAME MATCHES "Linux") set(kwin_SRCS ${kwin_SRCS} colorcorrection/clockskewnotifierengine_linux.cpp ) endif() include(ECMQtDeclareLoggingCategory) ecm_qt_declare_logging_category(kwin_SRCS HEADER colorcorrect_logging.h IDENTIFIER KWIN_COLORCORRECTION CATEGORY_NAME kwin_colorcorrection DEFAULT_SEVERITY Critical ) if (KWIN_BUILD_TABBOX) include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS}) set(kwin_SRCS ${kwin_SRCS} tabbox/clientmodel.cpp tabbox/desktopchain.cpp tabbox/desktopmodel.cpp tabbox/switcheritem.cpp tabbox/tabbox.cpp tabbox/tabbox_logging.cpp tabbox/tabboxconfig.cpp tabbox/tabboxhandler.cpp tabbox/x11_filter.cpp ) endif() if (KWIN_BUILD_ACTIVITIES) set(kwin_SRCS ${kwin_SRCS} activities.cpp ) endif() if (HAVE_LINUX_VT_H) set(kwin_SRCS ${kwin_SRCS} virtual_terminal.cpp ) + set(KWIN_TTY_PREFIX "/dev/tty") endif() if(CMAKE_SYSTEM MATCHES "FreeBSD") # We know it has epoll, so supports VT as well set(kwin_SRCS ${kwin_SRCS} virtual_terminal.cpp ) + set(KWIN_TTY_PREFIX "/dev/ttyv") endif() +if(KWIN_TTY_PREFIX) + set_source_files_properties(virtual_terminal.cpp PROPERTIES COMPILE_DEFINITIONS KWIN_TTY_PREFIX="${KWIN_TTY_PREFIX}") +endif() kconfig_add_kcfg_files(kwin_SRCS settings.kcfgc) kconfig_add_kcfg_files(kwin_SRCS colorcorrection/colorcorrect_settings.kcfgc) kconfig_add_kcfg_files(kwin_SRCS rulesettings.kcfgc) kconfig_add_kcfg_files(kwin_SRCS rulebooksettingsbase.kcfgc) qt5_add_dbus_adaptor(kwin_SRCS org.kde.KWin.xml dbusinterface.h KWin::DBusInterface) qt5_add_dbus_adaptor(kwin_SRCS org.kde.kwin.Compositing.xml dbusinterface.h KWin::CompositorDBusInterface) qt5_add_dbus_adaptor(kwin_SRCS org.kde.kwin.ColorCorrect.xml colorcorrection/colorcorrectdbusinterface.h KWin::ColorCorrect::ColorCorrectDBusInterface) qt5_add_dbus_adaptor(kwin_SRCS ${kwin_effects_dbus_xml} effects.h KWin::EffectsHandlerImpl) qt5_add_dbus_adaptor(kwin_SRCS org.kde.KWin.VirtualDesktopManager.xml dbusinterface.h KWin::VirtualDesktopManagerDBusInterface) qt5_add_dbus_adaptor(kwin_SRCS org.kde.KWin.Session.xml sm.h KWin::SessionManager) qt5_add_dbus_interface(kwin_SRCS ${KSCREENLOCKER_DBUS_INTERFACES_DIR}/kf5_org.freedesktop.ScreenSaver.xml screenlocker_interface) qt5_add_dbus_interface(kwin_SRCS ${KSCREENLOCKER_DBUS_INTERFACES_DIR}/org.kde.screensaver.xml kscreenlocker_interface) qt5_add_dbus_interface(kwin_SRCS org.kde.kappmenu.xml appmenu_interface) ki18n_wrap_ui(kwin_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::Script Qt5::Sensors ) set(kwin_KDE_LIBS KF5::ConfigCore KF5::ConfigWidgets KF5::CoreAddons KF5::GlobalAccel KF5::GlobalAccelPrivate KF5::I18n KF5::Notifications KF5::Package KF5::Plasma KF5::QuickAddons KF5::WindowSystem KDecoration2::KDecoration KDecoration2::KDecoration2Private PW::KScreenLocker ) set(kwin_XLIB_LIBS ${X11_ICE_LIB} ${X11_SM_LIB} ${X11_X11_LIB} ) set(kwin_XCB_LIBS XCB::COMPOSITE XCB::DAMAGE XCB::GLX XCB::ICCCM XCB::KEYSYMS XCB::RANDR XCB::RENDER XCB::SHAPE XCB::SHM XCB::SYNC XCB::XCB XCB::XFIXES ) set(kwin_WAYLAND_LIBS KF5::WaylandClient Plasma::KWaylandServer Wayland::Cursor XKB::XKB ${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_SRCS}) if (Libinput_VERSION_STRING VERSION_GREATER 1.14) target_compile_definitions(kwin PRIVATE -DLIBINPUT_HAS_TOTEM) endif () set_target_properties(kwin PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} ) target_link_libraries(kwin ${kwinLibs} kwinglutils ${epoxy_LIBRARY}) generate_export_header(kwin EXPORT_FILE_NAME kwin_export.h) if(CMAKE_SYSTEM MATCHES "FreeBSD") # epoll is required, includes live under ${LOCALBASE}, separate library target_include_directories(kwin PUBLIC ${epoll_INCLUDE_DIRS}) target_link_libraries(kwin ${kwinLibs} ${epoll_LIBRARIES}) endif() add_executable(kwin_x11 main_x11.cpp) target_link_libraries(kwin_x11 kwin KF5::Crash Qt5::X11Extras) install(TARGETS kwin ${INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY NAMELINK_SKIP) install(TARGETS kwin_x11 ${INSTALL_TARGETS_DEFAULT_ARGS}) set(kwin_XWAYLAND_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/xwl/clipboard.cpp ${CMAKE_CURRENT_SOURCE_DIR}/xwl/databridge.cpp ${CMAKE_CURRENT_SOURCE_DIR}/xwl/dnd.cpp ${CMAKE_CURRENT_SOURCE_DIR}/xwl/drag.cpp ${CMAKE_CURRENT_SOURCE_DIR}/xwl/drag_wl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/xwl/drag_x.cpp ${CMAKE_CURRENT_SOURCE_DIR}/xwl/selection.cpp ${CMAKE_CURRENT_SOURCE_DIR}/xwl/selection_source.cpp ${CMAKE_CURRENT_SOURCE_DIR}/xwl/transfer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/xwl/xwayland.cpp ) include(ECMQtDeclareLoggingCategory) ecm_qt_declare_logging_category(kwin_XWAYLAND_SRCS HEADER xwayland_logging.h IDENTIFIER KWIN_XWL CATEGORY_NAME kwin_xwl DEFAULT_SEVERITY Critical ) set(kwin_WAYLAND_SRCS main_wayland.cpp tabletmodemanager.cpp ) add_executable(kwin_wayland ${kwin_WAYLAND_SRCS} ${kwin_XWAYLAND_SRCS}) target_link_libraries(kwin_wayland kwin KF5::Crash) 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.VirtualDesktopManager.xml org.kde.KWin.xml org.kde.kwin.ColorCorrect.xml org.kde.kwin.Compositing.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}) add_subdirectory(qml) if (BUILD_TESTING) add_subdirectory(autotests) add_subdirectory(tests) endif() if (KF5DocTools_FOUND) add_subdirectory(doc) endif() add_subdirectory(kconf_update) # add clang-format target for all our real source files file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES *.cpp *.h) kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES}) 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/udev.cpp b/udev.cpp index da3b6072b..834b24a84 100644 --- a/udev.cpp +++ b/udev.cpp @@ -1,293 +1,297 @@ /******************************************************************** 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 "udev.h" #include "logind.h" // Qt #include #include // system #include #include namespace KWin { Udev::Udev() : m_udev(udev_new()) { } Udev::~Udev() { if (m_udev) { udev_unref(m_udev); } } class UdevEnumerate { public: UdevEnumerate(Udev *udev); ~UdevEnumerate(); enum class Match { SubSystem, SysName }; void addMatch(Match match, const char *name); void scan(); UdevDevice::Ptr find(std::function test); private: Udev *m_udev; struct EnumerateDeleter { static inline void cleanup(udev_enumerate *e) { udev_enumerate_unref(e); } }; QScopedPointer m_enumerate; }; UdevEnumerate::UdevEnumerate(Udev *udev) : m_udev(udev) , m_enumerate(udev_enumerate_new(*m_udev)) { } UdevEnumerate::~UdevEnumerate() = default; void UdevEnumerate::addMatch(UdevEnumerate::Match match, const char *name) { if (m_enumerate.isNull()) { return; } switch (match) { case Match::SubSystem: udev_enumerate_add_match_subsystem(m_enumerate.data(), name); break; case Match::SysName: udev_enumerate_add_match_sysname(m_enumerate.data(), name); break; default: Q_UNREACHABLE(); break; } } void UdevEnumerate::scan() { if (m_enumerate.isNull()) { return; } udev_enumerate_scan_devices(m_enumerate.data()); } UdevDevice::Ptr UdevEnumerate::find(std::function test) { if (m_enumerate.isNull()) { return UdevDevice::Ptr(); } QString defaultSeat = QStringLiteral("seat0"); udev_list_entry *it = udev_enumerate_get_list_entry(m_enumerate.data()); UdevDevice::Ptr firstFound; while (it) { auto current = it; it = udev_list_entry_get_next(it); auto device = m_udev->deviceFromSyspath(udev_list_entry_get_name(current)); if (!device) { continue; } QString deviceSeat = device->property("ID_SEAT"); if (deviceSeat.isEmpty()) { deviceSeat = defaultSeat; } if (deviceSeat != LogindIntegration::self()->seat()) { continue; } if (test(device)) { return device; } if (!firstFound) { firstFound.swap(device); } } return firstFound; } UdevDevice::Ptr Udev::primaryGpu() { if (!m_udev) { return UdevDevice::Ptr(); } +#if defined(Q_OS_FREEBSD) + return deviceFromSyspath("/dev/dri/card0"); +#else UdevEnumerate enumerate(this); enumerate.addMatch(UdevEnumerate::Match::SubSystem, "drm"); enumerate.addMatch(UdevEnumerate::Match::SysName, "card[0-9]*"); enumerate.scan(); return enumerate.find([](const UdevDevice::Ptr &device) { auto pci = device->getParentWithSubsystemDevType("pci"); if (!pci) { return false; } const char *systAttrValue = udev_device_get_sysattr_value(pci, "boot_vga"); if (systAttrValue && qstrcmp(systAttrValue, "1") == 0) { return true; } return false; }); +#endif } UdevDevice::Ptr Udev::primaryFramebuffer() { if (!m_udev) { return UdevDevice::Ptr(); } UdevEnumerate enumerate(this); enumerate.addMatch(UdevEnumerate::Match::SubSystem, "graphics"); enumerate.addMatch(UdevEnumerate::Match::SysName, "fb[0-9]*"); enumerate.scan(); return enumerate.find([](const UdevDevice::Ptr &device) { auto pci = device->getParentWithSubsystemDevType("pci"); if (!pci) { return false; } const char *systAttrValue = udev_device_get_sysattr_value(pci, "boot_vga"); if (systAttrValue && qstrcmp(systAttrValue, "1") == 0) { return true; } return false; }); } UdevDevice::Ptr Udev::deviceFromSyspath(const char *syspath) { return UdevDevice::Ptr(new UdevDevice(udev_device_new_from_syspath(m_udev, syspath))); } UdevMonitor *Udev::monitor() { UdevMonitor *m = new UdevMonitor(this); if (!m->isValid()) { delete m; m = nullptr; } return m; } UdevDevice::UdevDevice(udev_device *device) : m_device(device) { } UdevDevice::~UdevDevice() { if (m_device) { udev_device_unref(m_device); } } udev_device *UdevDevice::getParentWithSubsystemDevType(const char *subsystem, const char *devtype) const { if (!m_device) { return nullptr; } return udev_device_get_parent_with_subsystem_devtype(m_device, subsystem, devtype); } const char *UdevDevice::devNode() { if (!m_device) { return nullptr; } return udev_device_get_devnode(m_device); } int UdevDevice::sysNum() const { if (!m_device) { return 0; } return QByteArray(udev_device_get_sysnum(m_device)).toInt(); } const char *UdevDevice::property(const char *key) { if (!m_device) { return nullptr; } return udev_device_get_property_value(m_device, key); } bool UdevDevice::hasProperty(const char *key, const char *value) { const char *p = property(key); if (!p) { return false; } return qstrcmp(p, value) == 0; } UdevMonitor::UdevMonitor(Udev *udev) : m_monitor(udev_monitor_new_from_netlink(*udev, "udev")) { } UdevMonitor::~UdevMonitor() { if (m_monitor) { udev_monitor_unref(m_monitor); } } int UdevMonitor::fd() const { if (m_monitor) { return udev_monitor_get_fd(m_monitor); } return -1; } void UdevMonitor::filterSubsystemDevType(const char *subSystem, const char *devType) { if (!m_monitor) { return; } udev_monitor_filter_add_match_subsystem_devtype(m_monitor, subSystem, devType); } void UdevMonitor::enable() { if (!m_monitor) { return; } udev_monitor_enable_receiving(m_monitor); } UdevDevice::Ptr UdevMonitor::getDevice() { if (!m_monitor) { return UdevDevice::Ptr(); } return UdevDevice::Ptr(new UdevDevice(udev_monitor_receive_device(m_monitor))); } } diff --git a/virtual_terminal.cpp b/virtual_terminal.cpp index b73983d13..f8f6a324a 100644 --- a/virtual_terminal.cpp +++ b/virtual_terminal.cpp @@ -1,226 +1,226 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2015 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 "virtual_terminal.h" // kwin #include "logind.h" #include "main.h" #include "utils.h" // Qt #include #include // linux #ifdef Q_OS_LINUX #include #include #include #include #endif #ifdef Q_OS_FREEBSD #include #endif // system #include #include #include #include #include // c++ #include #define RELEASE_SIGNAL SIGUSR1 #define ACQUISITION_SIGNAL SIGUSR2 namespace KWin { KWIN_SINGLETON_FACTORY(VirtualTerminal) VirtualTerminal::VirtualTerminal(QObject *parent) : QObject(parent) { } void VirtualTerminal::init() { auto logind = LogindIntegration::self(); if (logind->vt() != -1) { setup(logind->vt()); } connect(logind, &LogindIntegration::virtualTerminalChanged, this, &VirtualTerminal::setup); if (logind->isConnected()) { logind->takeControl(); } else { connect(logind, &LogindIntegration::connectedChanged, logind, &LogindIntegration::takeControl); } } VirtualTerminal::~VirtualTerminal() { s_self = nullptr; closeFd(); } static bool isTty(int fd) { if (fd < 0) { return false; } struct stat st; if (fstat(fd, &st) == -1) { return false; } #ifdef Q_OS_LINUX // Not a TTY device or weird vt number, skip it if (major(st.st_rdev) != TTY_MAJOR || minor (st.st_rdev) <= 0 || minor(st.st_rdev) >= 64) { return false; } #endif // FreeBSD doesn't have a notion of major device number, so nothing // to check. isatty() might not do the trick. return true; } void VirtualTerminal::setup(int vtNr) { if (m_vt != -1) { return; } if (vtNr == -1) { // error condition return; } - QString ttyName = QStringLiteral("/dev/tty%1").arg(vtNr); + QString ttyName = QStringLiteral(KWIN_TTY_PREFIX "%1").arg(vtNr); m_vt = open(ttyName.toUtf8().constData(), O_RDWR|O_CLOEXEC|O_NONBLOCK); if (m_vt < 0) { qCWarning(KWIN_CORE) << "Failed to open tty" << vtNr; return; } if (!isTty(m_vt)) { qCWarning(KWIN_CORE) << vtNr << " is no tty"; closeFd(); return; } if (ioctl(m_vt, KDSETMODE, KD_GRAPHICS) < 0) { qCWarning(KWIN_CORE()) << "Failed to set tty " << vtNr << " in graphics mode"; closeFd(); return; } if (!createSignalHandler()) { qCWarning(KWIN_CORE) << "Failed to create signalfd"; closeFd(); return; } vt_mode mode = { VT_PROCESS, 0, RELEASE_SIGNAL, ACQUISITION_SIGNAL, 0 }; if (ioctl(m_vt, VT_SETMODE, &mode) < 0) { qCWarning(KWIN_CORE) << "Failed to take over virtual terminal"; closeFd(); return; } m_vtNumber = vtNr; setActive(true); emit kwinApp()->virtualTerminalCreated(); } void VirtualTerminal::closeFd() { if (m_vt < 0) { return; } if (m_notifier) { const int sfd = m_notifier->socket(); delete m_notifier; m_notifier = nullptr; close(sfd); } close(m_vt); m_vt = -1; } bool VirtualTerminal::createSignalHandler() { if (m_notifier) { return false; } sigset_t mask; sigemptyset(&mask); sigaddset(&mask, RELEASE_SIGNAL); sigaddset(&mask, ACQUISITION_SIGNAL); pthread_sigmask(SIG_BLOCK, &mask, nullptr); const int fd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC); if (fd < 0) { return false; } m_notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); connect(m_notifier, &QSocketNotifier::activated, this, [this] { if (m_vt < 0) { return; } while (true) { signalfd_siginfo sigInfo; if (read(m_notifier->socket(), &sigInfo, sizeof(sigInfo)) != sizeof(sigInfo)) { break; } switch (sigInfo.ssi_signo) { case RELEASE_SIGNAL: setActive(false); ioctl(m_vt, VT_RELDISP, 1); break; case ACQUISITION_SIGNAL: ioctl(m_vt, VT_RELDISP, VT_ACKACQ); setActive(true); break; } } } ); return true; } void VirtualTerminal::activate(int vt) { if (m_vt < 0) { return; } if (vt == m_vtNumber) { return; } ioctl(m_vt, VT_ACTIVATE, vt); setActive(false); } void VirtualTerminal::setActive(bool active) { if (m_active == active) { return; } m_active = active; emit activeChanged(m_active); } }