diff --git a/CMakeLists.txt b/CMakeLists.txt index 626e7e227..44faa69b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,638 +1,645 @@ project(KWIN) set(PROJECT_VERSION "5.7.90") set(PROJECT_VERSION_MAJOR 5) cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) set(QT_MIN_VERSION "5.5.0") set(KF5_MIN_VERSION "5.24.0") set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH} ) find_package(ECM 0.0.11 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 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) # require at least gcc 4.8 if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") if ("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.8") message(SEND_ERROR "Version ${CMAKE_CXX_COMPILER_VERSION} of the ${CMAKE_CXX_COMPILER_ID} C++ compiler is not supported. Please use version 4.8 or later.") endif() 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 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 CONFIG REQUIRED) find_package(KScreenLocker CONFIG REQUIRED) set_package_properties(KScreenLocker PROPERTIES TYPE REQUIRED PURPOSE "For screenlocker integration in kwin_wayland") find_package(Breeze ${PROJECT_VERSION} 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" ) 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.4.1) set_package_properties(XKB PROPERTIES TYPE REQUIRED PURPOSE "Required for building KWin with Wayland support" ) find_package(Libinput 0.10) set_package_properties(Libinput PROPERTIES TYPE OPTIONAL 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 OPTIONAL PURPOSE "Required for input handling on Wayland." ) set(HAVE_INPUT FALSE) if (Libinput_FOUND AND UDEV_FOUND) set(HAVE_INPUT TRUE) endif() set(HAVE_UDEV FALSE) if (UDEV_FOUND) set(HAVE_UDEV TRUE) endif() +set(HAVE_LIBINPUT_1_2 FALSE) +if (Libinput_FOUND) + if (NOT (Libinput_VERSION VERSION_LESS "1.2")) + set(HAVE_LIBINPUT_1_2 TRUE) + endif() +endif() + find_package(Libdrm) set_package_properties(Libdrm PROPERTIES TYPE OPTIONAL PURPOSE "Required for drm output on Wayland.") set(HAVE_DRM FALSE) if(Libdrm_FOUND AND UDEV_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 OPTIONAL_COMPONENTS 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(Qt5PlatformSupport REQUIRED) find_package(Freetype REQUIRED) set_package_properties(Freetype PROPERTIES DESCRIPTION "A font rendering engine" URL "http://www.freetype.org" TYPE REQUIRED PURPOSE "Needed for KWin's QPA plugin." ) find_package(Fontconfig REQUIRED) set_package_properties(Fontconfig PROPERTIES DESCRIPTION "Font access configuration library" URL "http://www.freedesktop.org/wiki/Software/fontconfig" TYPE REQUIRED PURPOSE "Needed for KWin's QPA plugin." ) find_package(Xwayland) set_package_properties(Xwayland PROPERTIES URL "http://x.org" DESCRIPTION "Xwayland X server" TYPE RUNTIME PURPOSE "Needed for running kwin_wayland" ) ########### 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_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") 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) 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 ) 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 keyboard_input.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 scene_xrender.cpp scene_opengl.cpp scene_qpainter.cpp thumbnailitem.cpp lanczosfilter.cpp deleted.cpp effects.cpp effectloader.cpp virtualdesktops.cpp xcbutils.cpp x11eventfilter.cpp logind.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 abstract_egl_backend.cpp platform.cpp shell_client.cpp wayland_server.cpp wayland_cursor_theme.cpp virtualkeyboard.cpp ) 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 ) endif() if(KWIN_BUILD_ACTIVITIES) set( kwin_KDEINIT_SRCS ${kwin_KDEINIT_SRCS} activities.cpp ) endif() if(UDEV_FOUND) set(kwin_KDEINIT_SRCS ${kwin_KDEINIT_SRCS} udev.cpp ) endif() if(HAVE_INPUT) set(kwin_KDEINIT_SRCS ${kwin_KDEINIT_SRCS} libinput/context.cpp libinput/connection.cpp libinput/device.cpp libinput/events.cpp libinput/libinput_logging.cpp virtual_terminal.cpp ) endif() kconfig_add_kcfg_files(kwin_KDEINIT_SRCS 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 ${kwin_effects_dbus_xml} effects.h KWin::EffectsHandlerImpl ) qt5_add_dbus_interface( kwin_KDEINIT_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/org.freedesktop.ScreenSaver.xml screenlocker_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 kwinxrenderutils kwin4_effect_builtins ) set(kwin_QT_LIBS Qt5::Concurrent Qt5::DBus Qt5::Quick Qt5::Script Qt5::X11Extras ) set(kwin_KDE_LIBS KF5::ConfigCore KF5::CoreAddons KF5::ConfigWidgets KF5::GlobalAccel KF5::GlobalAccelPrivate KF5::I18n KF5::Notifications KF5::Package KF5::Plasma KF5::WindowSystem KDecoration2::KDecoration KDecoration2::KDecoration2Private PW::KScreenLocker ) set(kwin_XLIB_LIBS ${X11_X11_LIB} ${X11_ICE_LIB} ${X11_SM_LIB} ) if(X11_Xinput_FOUND) set(kwin_XLIB_LIBS ${kwin_XLIB_LIBS} ${X11_Xinput_LIB}) endif() 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::CURSOR ) 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} ) if(UDEV_FOUND) set(kwinLibs ${kwinLibs} ${UDEV_LIBS}) endif() if(HAVE_INPUT) set(kwinLibs ${kwinLibs} Libinput::Libinput) endif() 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}) # -ldl used by OpenGL code find_library(DL_LIBRARY dl) if (DL_LIBRARY) target_link_libraries(kwin ${DL_LIBRARY}) endif() kf5_add_kdeinit_executable(kwin_x11 main_x11.cpp) target_link_libraries(kdeinit_kwin_x11 kwin KF5::Crash) 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 main_wayland.cpp) target_link_libraries(kwin_wayland kwin) install(TARGETS kwin_wayland ${INSTALL_TARGETS_DEFAULT_ARGS} ) add_subdirectory(plugins) ########### install files ############### install( FILES kwin.kcfg DESTINATION ${KCFG_INSTALL_DIR} RENAME ${KWIN_NAME}.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.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(autotests) add_subdirectory(tests) if (KF5DocTools_FOUND) add_subdirectory(doc) endif() feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) include(ECMPackageConfigHelpers) set(CMAKECONFIG_INSTALL_DIR "${CMAKECONFIG_INSTALL_PREFIX}/KWinDBusInterface") ecm_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/libinput/device_test.cpp b/autotests/libinput/device_test.cpp index 5bb2a6a91..92dcf7989 100644 --- a/autotests/libinput/device_test.cpp +++ b/autotests/libinput/device_test.cpp @@ -1,605 +1,615 @@ /******************************************************************** 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 "mock_libinput.h" #include "../../libinput/device.h" +#include #include #include using namespace KWin::LibInput; class TestLibinputDevice : public QObject { Q_OBJECT private Q_SLOTS: void testStaticGetter(); void testDeviceType_data(); void testDeviceType(); void testGestureSupport_data(); void testGestureSupport(); void testNames_data(); void testNames(); void testProduct(); void testVendor(); void testTapFingerCount(); void testSize_data(); void testSize(); void testTapEnabledByDefault_data(); void testTapEnabledByDefault(); void testSupportsDisableWhileTyping_data(); void testSupportsDisableWhileTyping(); void testSupportsPointerAcceleration_data(); void testSupportsPointerAcceleration(); void testSupportsLeftHanded_data(); void testSupportsLeftHanded(); void testSupportsCalibrationMatrix_data(); void testSupportsCalibrationMatrix(); void testSupportsDisableEvents_data(); void testSupportsDisableEvents(); void testSupportsDisableEventsOnExternalMouse_data(); void testSupportsDisableEventsOnExternalMouse(); void testPointerAcceleration_data(); void testPointerAcceleration(); void testLeftHanded_data(); void testLeftHanded(); void testSupportedButtons_data(); void testSupportedButtons(); void testAlphaNumericKeyboard_data(); void testAlphaNumericKeyboard(); void testEnabled_data(); void testEnabled(); }; void TestLibinputDevice::testStaticGetter() { // this test verifies that the static getter for Device works as expected QVERIFY(Device::devices().isEmpty()); // create some device libinput_device device1; libinput_device device2; // at the moment not yet known to Device QVERIFY(!Device::getDevice(&device1)); QVERIFY(!Device::getDevice(&device2)); QVERIFY(Device::devices().isEmpty()); // now create a Device for one Device *d1 = new Device(&device1); QCOMPARE(Device::devices().count(), 1); QCOMPARE(Device::devices().first(), d1); QCOMPARE(Device::getDevice(&device1), d1); QVERIFY(!Device::getDevice(&device2)); // and a second Device Device *d2 = new Device(&device2); QCOMPARE(Device::devices().count(), 2); QCOMPARE(Device::devices().first(), d1); QCOMPARE(Device::devices().last(), d2); QCOMPARE(Device::getDevice(&device1), d1); QCOMPARE(Device::getDevice(&device2), d2); // now delete d1 delete d1; QCOMPARE(Device::devices().count(), 1); QCOMPARE(Device::devices().first(), d2); QCOMPARE(Device::getDevice(&device2), d2); QVERIFY(!Device::getDevice(&device1)); // and delete d2 delete d2; QVERIFY(!Device::getDevice(&device1)); QVERIFY(!Device::getDevice(&device2)); QVERIFY(Device::devices().isEmpty()); } void TestLibinputDevice::testDeviceType_data() { QTest::addColumn("keyboard"); QTest::addColumn("pointer"); QTest::addColumn("touch"); + QTest::addColumn("tabletTool"); - QTest::newRow("keyboard") << true << false << false; - QTest::newRow("pointer") << false << true << false; - QTest::newRow("touch") << false << false << true; - QTest::newRow("keyboard/pointer") << true << true << false; - QTest::newRow("keyboard/touch") << true << false << true; - QTest::newRow("pointer/touch") << false << true << true; - QTest::newRow("keyboard/pointer/touch") << true << true << true; + QTest::newRow("keyboard") << true << false << false << false; + QTest::newRow("pointer") << false << true << false << false; + QTest::newRow("touch") << false << false << true << false; + QTest::newRow("keyboard/pointer") << true << true << false << false; + QTest::newRow("keyboard/touch") << true << false << true << false; + QTest::newRow("pointer/touch") << false << true << true << false; + QTest::newRow("keyboard/pointer/touch") << true << true << true << false; + QTest::newRow("tabletTool") << false << false << false << true; } void TestLibinputDevice::testDeviceType() { // this test verifies that the device type is recognized correctly QFETCH(bool, keyboard); QFETCH(bool, pointer); QFETCH(bool, touch); + QFETCH(bool, tabletTool); libinput_device device; device.keyboard = keyboard; device.pointer = pointer; device.touch = touch; + device.tabletTool = tabletTool; Device d(&device); QCOMPARE(d.isKeyboard(), keyboard); QCOMPARE(d.property("keyboard").toBool(), keyboard); QCOMPARE(d.isPointer(), pointer); QCOMPARE(d.property("pointer").toBool(), pointer); QCOMPARE(d.isTouch(), touch); QCOMPARE(d.property("touch").toBool(), touch); QCOMPARE(d.isTabletPad(), false); QCOMPARE(d.property("tabletPad").toBool(), false); +#if HAVE_LIBINPUT_1_2 + QCOMPARE(d.isTabletTool(), tabletTool); + QCOMPARE(d.property("tabletTool").toBool(), tabletTool); +#else QCOMPARE(d.isTabletTool(), false); QCOMPARE(d.property("tabletTool").toBool(), false); +#endif QCOMPARE(d.device(), &device); } void TestLibinputDevice::testGestureSupport_data() { QTest::addColumn("supported"); QTest::newRow("supported") << true; QTest::newRow("not supported") << false; } void TestLibinputDevice::testGestureSupport() { // this test verifies whether the Device supports gestures QFETCH(bool, supported); libinput_device device; device.gestureSupported = supported; Device d(&device); QCOMPARE(d.supportsGesture(), supported); QCOMPARE(d.property("gestureSupport").toBool(), supported); } void TestLibinputDevice::testNames_data() { QTest::addColumn("name"); QTest::addColumn("sysName"); QTest::addColumn("outputName"); QTest::newRow("empty") << QByteArray() << QByteArray() << QByteArray(); QTest::newRow("set") << QByteArrayLiteral("awesome test device") << QByteArrayLiteral("event0") << QByteArrayLiteral("hdmi0"); } void TestLibinputDevice::testNames() { // this test verifies the various name properties of the Device QFETCH(QByteArray, name); QFETCH(QByteArray, sysName); QFETCH(QByteArray, outputName); libinput_device device; device.name = name; device.sysName = sysName; device.outputName = outputName; Device d(&device); QCOMPARE(d.name().toUtf8(), name); QCOMPARE(d.property("name").toString().toUtf8(), name); QCOMPARE(d.sysName().toUtf8(), sysName); QCOMPARE(d.property("sysName").toString().toUtf8(), sysName); QCOMPARE(d.outputName().toUtf8(), outputName); QCOMPARE(d.property("outputName").toString().toUtf8(), outputName); } void TestLibinputDevice::testProduct() { // this test verifies the product property libinput_device device; device.product = 100u; Device d(&device); QCOMPARE(d.product(), 100u); QCOMPARE(d.property("product").toUInt(), 100u); } void TestLibinputDevice::testVendor() { // this test verifies the vendor property libinput_device device; device.vendor = 200u; Device d(&device); QCOMPARE(d.vendor(), 200u); QCOMPARE(d.property("vendor").toUInt(), 200u); } void TestLibinputDevice::testTapFingerCount() { // this test verifies the tap finger count property libinput_device device; device.tapFingerCount = 3; Device d(&device); QCOMPARE(d.tapFingerCount(), 3); QCOMPARE(d.property("tapFingerCount").toInt(), 3); } void TestLibinputDevice::testSize_data() { QTest::addColumn("setSize"); QTest::addColumn("returnValue"); QTest::addColumn("expectedSize"); QTest::newRow("10/20") << QSizeF(10.5, 20.2) << 0 << QSizeF(10.5, 20.2); QTest::newRow("failure") << QSizeF(10, 20) << 1 << QSizeF(); } void TestLibinputDevice::testSize() { // this test verifies that getting the size works correctly including failures QFETCH(QSizeF, setSize); QFETCH(int, returnValue); libinput_device device; device.deviceSize = setSize; device.deviceSizeReturnValue = returnValue; Device d(&device); QTEST(d.size(), "expectedSize"); QTEST(d.property("size").toSizeF(), "expectedSize"); } void TestLibinputDevice::testTapEnabledByDefault_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testTapEnabledByDefault() { QFETCH(bool, enabled); libinput_device device; device.tapEnabledByDefault = enabled; Device d(&device); QCOMPARE(d.tapEnabledByDefault(), enabled); QCOMPARE(d.property("tapEnabledByDefault").toBool(), enabled); } void TestLibinputDevice::testSupportsDisableWhileTyping_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testSupportsDisableWhileTyping() { QFETCH(bool, enabled); libinput_device device; device.supportsDisableWhileTyping = enabled; Device d(&device); QCOMPARE(d.supportsDisableWhileTyping(), enabled); QCOMPARE(d.property("supportsDisableWhileTyping").toBool(), enabled); } void TestLibinputDevice::testSupportsPointerAcceleration_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testSupportsPointerAcceleration() { QFETCH(bool, enabled); libinput_device device; device.supportsPointerAcceleration = enabled; Device d(&device); QCOMPARE(d.supportsPointerAcceleration(), enabled); QCOMPARE(d.property("supportsPointerAcceleration").toBool(), enabled); } void TestLibinputDevice::testSupportsLeftHanded_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testSupportsLeftHanded() { QFETCH(bool, enabled); libinput_device device; device.supportsLeftHanded = enabled; Device d(&device); QCOMPARE(d.supportsLeftHanded(), enabled); QCOMPARE(d.property("supportsLeftHanded").toBool(), enabled); } void TestLibinputDevice::testSupportsCalibrationMatrix_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testSupportsCalibrationMatrix() { QFETCH(bool, enabled); libinput_device device; device.supportsCalibrationMatrix = enabled; Device d(&device); QCOMPARE(d.supportsCalibrationMatrix(), enabled); QCOMPARE(d.property("supportsCalibrationMatrix").toBool(), enabled); } void TestLibinputDevice::testSupportsDisableEvents_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testSupportsDisableEvents() { QFETCH(bool, enabled); libinput_device device; device.supportsDisableEvents = enabled; Device d(&device); QCOMPARE(d.supportsDisableEvents(), enabled); QCOMPARE(d.property("supportsDisableEvents").toBool(), enabled); } void TestLibinputDevice::testSupportsDisableEventsOnExternalMouse_data() { QTest::addColumn("enabled"); QTest::newRow("enabled") << true; QTest::newRow("disabled") << false; } void TestLibinputDevice::testSupportsDisableEventsOnExternalMouse() { QFETCH(bool, enabled); libinput_device device; device.supportsDisableEventsOnExternalMouse = enabled; Device d(&device); QCOMPARE(d.supportsDisableEventsOnExternalMouse(), enabled); QCOMPARE(d.property("supportsDisableEventsOnExternalMouse").toBool(), enabled); } void TestLibinputDevice::testPointerAcceleration_data() { QTest::addColumn("supported"); QTest::addColumn("setShouldFail"); QTest::addColumn("accel"); QTest::addColumn("setAccel"); QTest::addColumn("expectedAccel"); QTest::addColumn("expectedChanged"); QTest::newRow("-1 -> 2.0") << true << false << -1.0 << 2.0 << 1.0 << true; QTest::newRow("0 -> -1.0") << true << false << 0.0 << -1.0 << -1.0 << true; QTest::newRow("1 -> 1") << true << false << 1.0 << 1.0 << 1.0 << false; QTest::newRow("unsupported") << false << false << 0.0 << 1.0 << 0.0 << false; QTest::newRow("set fails") << true << true << -1.0 << 1.0 << -1.0 << false; } void TestLibinputDevice::testPointerAcceleration() { QFETCH(bool, supported); QFETCH(bool, setShouldFail); QFETCH(qreal, accel); libinput_device device; device.supportsPointerAcceleration = supported; device.pointerAcceleration = accel; device.setPointerAccelerationReturnValue = setShouldFail; Device d(&device); QCOMPARE(d.pointerAcceleration(), accel); QCOMPARE(d.property("pointerAcceleration").toReal(), accel); QSignalSpy pointerAccelChangedSpy(&d, &Device::pointerAccelerationChanged); QVERIFY(pointerAccelChangedSpy.isValid()); QFETCH(qreal, setAccel); d.setPointerAcceleration(setAccel); QTEST(d.pointerAcceleration(), "expectedAccel"); QTEST(!pointerAccelChangedSpy.isEmpty(), "expectedChanged"); } void TestLibinputDevice::testLeftHanded_data() { QTest::addColumn("supported"); QTest::addColumn("setShouldFail"); QTest::addColumn("initValue"); QTest::addColumn("setValue"); QTest::addColumn("expectedValue"); QTest::newRow("unsupported/true") << false << false << true << false << false; QTest::newRow("unsupported/false") << false << false << false << true << false; QTest::newRow("true -> false") << true << false << true << false << false; QTest::newRow("false -> true") << true << false << false << true << true; QTest::newRow("set fails") << true << true << true << false << true; QTest::newRow("true -> true") << true << false << true << true << true; QTest::newRow("false -> false") << true << false << false << false << false; } void TestLibinputDevice::testLeftHanded() { QFETCH(bool, supported); QFETCH(bool, setShouldFail); QFETCH(bool, initValue); libinput_device device; device.supportsLeftHanded = supported; device.leftHanded = initValue; device.setLeftHandedReturnValue = setShouldFail; Device d(&device); QCOMPARE(d.isLeftHanded(), supported && initValue); QCOMPARE(d.property("leftHanded").toBool(), supported && initValue); QSignalSpy leftHandedChangedSpy(&d, &Device::leftHandedChanged); QVERIFY(leftHandedChangedSpy.isValid()); QFETCH(bool, setValue); d.setLeftHanded(setValue); QFETCH(bool, expectedValue); QCOMPARE(d.isLeftHanded(), expectedValue); QCOMPARE(leftHandedChangedSpy.isEmpty(), (supported && initValue) == expectedValue); } void TestLibinputDevice::testSupportedButtons_data() { QTest::addColumn("isPointer"); QTest::addColumn("setButtons"); QTest::addColumn("expectedButtons"); QTest::newRow("left") << true << Qt::MouseButtons(Qt::LeftButton) << Qt::MouseButtons(Qt::LeftButton); QTest::newRow("right") << true << Qt::MouseButtons(Qt::RightButton) << Qt::MouseButtons(Qt::RightButton); QTest::newRow("middle") << true << Qt::MouseButtons(Qt::MiddleButton) << Qt::MouseButtons(Qt::MiddleButton); QTest::newRow("extra1") << true << Qt::MouseButtons(Qt::ExtraButton1) << Qt::MouseButtons(Qt::ExtraButton1); QTest::newRow("extra2") << true << Qt::MouseButtons(Qt::ExtraButton2) << Qt::MouseButtons(Qt::ExtraButton2); QTest::newRow("back") << true << Qt::MouseButtons(Qt::BackButton) << Qt::MouseButtons(Qt::BackButton); QTest::newRow("forward") << true << Qt::MouseButtons(Qt::ForwardButton) << Qt::MouseButtons(Qt::ForwardButton); QTest::newRow("task") << true << Qt::MouseButtons(Qt::TaskButton) << Qt::MouseButtons(Qt::TaskButton); QTest::newRow("no pointer/left") << false << Qt::MouseButtons(Qt::LeftButton) << Qt::MouseButtons(); QTest::newRow("no pointer/right") << false << Qt::MouseButtons(Qt::RightButton) << Qt::MouseButtons(); QTest::newRow("no pointer/middle") << false << Qt::MouseButtons(Qt::MiddleButton) << Qt::MouseButtons(); QTest::newRow("no pointer/extra1") << false << Qt::MouseButtons(Qt::ExtraButton1) << Qt::MouseButtons(); QTest::newRow("no pointer/extra2") << false << Qt::MouseButtons(Qt::ExtraButton2) << Qt::MouseButtons(); QTest::newRow("no pointer/back") << false << Qt::MouseButtons(Qt::BackButton) << Qt::MouseButtons(); QTest::newRow("no pointer/forward") << false << Qt::MouseButtons(Qt::ForwardButton) << Qt::MouseButtons(); QTest::newRow("no pointer/task") << false << Qt::MouseButtons(Qt::TaskButton) << Qt::MouseButtons(); QTest::newRow("all") << true << Qt::MouseButtons(Qt::LeftButton | Qt::RightButton | Qt::MiddleButton | Qt::ExtraButton1 | Qt::ExtraButton2 | Qt::BackButton | Qt::ForwardButton | Qt::TaskButton) << Qt::MouseButtons(Qt::LeftButton | Qt::RightButton | Qt::MiddleButton | Qt::ExtraButton1 | Qt::ExtraButton2 | Qt::BackButton | Qt::ForwardButton | Qt::TaskButton); } void TestLibinputDevice::testSupportedButtons() { libinput_device device; QFETCH(bool, isPointer); device.pointer = isPointer; QFETCH(Qt::MouseButtons, setButtons); device.supportedButtons = setButtons; Device d(&device); QCOMPARE(d.isPointer(), isPointer); QTEST(d.supportedButtons(), "expectedButtons"); } void TestLibinputDevice::testAlphaNumericKeyboard_data() { QTest::addColumn>("supportedKeys"); QTest::addColumn("isAlpha"); QVector keys; for (int i = KEY_1; i <= KEY_0; i++) { keys << i; QByteArray row = QByteArrayLiteral("number"); row.append(QByteArray::number(i)); QTest::newRow(row.constData()) << keys << false; } for (int i = KEY_Q; i <= KEY_P; i++) { keys << i; QByteArray row = QByteArrayLiteral("alpha"); row.append(QByteArray::number(i)); QTest::newRow(row.constData()) << keys << false; } for (int i = KEY_A; i <= KEY_L; i++) { keys << i; QByteArray row = QByteArrayLiteral("alpha"); row.append(QByteArray::number(i)); QTest::newRow(row.constData()) << keys << false; } for (int i = KEY_Z; i < KEY_M; i++) { keys << i; QByteArray row = QByteArrayLiteral("alpha"); row.append(QByteArray::number(i)); QTest::newRow(row.constData()) << keys << false; } // adding a different key should not result in it becoming alphanumeric keyboard keys << KEY_SEMICOLON; QTest::newRow("semicolon") << keys << false; // last but not least the M which should turn everything on keys << KEY_M; QTest::newRow("alphanumeric") << keys << true; } void TestLibinputDevice::testAlphaNumericKeyboard() { QFETCH(QVector, supportedKeys); libinput_device device; device.keyboard = true; device.keys = supportedKeys; Device d(&device); QCOMPARE(d.isKeyboard(), true); QTEST(d.isAlphaNumericKeyboard(), "isAlpha"); } void TestLibinputDevice::testEnabled_data() { QTest::addColumn("supported"); QTest::addColumn("setShouldFail"); QTest::addColumn("initValue"); QTest::addColumn("setValue"); QTest::addColumn("expectedValue"); QTest::newRow("unsupported/true") << false << false << true << false << true; QTest::newRow("unsupported/false") << false << false << false << true << true; QTest::newRow("true -> false") << true << false << true << false << false; QTest::newRow("false -> true") << true << false << false << true << true; QTest::newRow("set fails") << true << true << true << false << true; QTest::newRow("true -> true") << true << false << true << true << true; QTest::newRow("false -> false") << true << false << false << false << false; } void TestLibinputDevice::testEnabled() { libinput_device device; QFETCH(bool, supported); QFETCH(bool, setShouldFail); QFETCH(bool, initValue); device.supportsDisableEvents = supported; device.enabled = initValue; device.setEnableModeReturnValue = setShouldFail; Device d(&device); QCOMPARE(d.isEnabled(), !supported || initValue); QCOMPARE(d.property("enabled").toBool(), !supported || initValue); QSignalSpy enabledChangedSpy(&d, &Device::enabledChanged); QVERIFY(enabledChangedSpy.isValid()); QFETCH(bool, setValue); d.setEnabled(setValue); QFETCH(bool, expectedValue); QCOMPARE(d.isEnabled(), expectedValue); } QTEST_GUILESS_MAIN(TestLibinputDevice) #include "device_test.moc" diff --git a/autotests/libinput/mock_libinput.cpp b/autotests/libinput/mock_libinput.cpp index 35ffd139f..93a487021 100644 --- a/autotests/libinput/mock_libinput.cpp +++ b/autotests/libinput/mock_libinput.cpp @@ -1,452 +1,457 @@ /******************************************************************** 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 #include "mock_libinput.h" +#include #include int libinput_device_keyboard_has_key(struct libinput_device *device, uint32_t code) { return device->keys.contains(code); } int libinput_device_has_capability(struct libinput_device *device, enum libinput_device_capability capability) { switch (capability) { case LIBINPUT_DEVICE_CAP_KEYBOARD: return device->keyboard; case LIBINPUT_DEVICE_CAP_POINTER: return device->pointer; case LIBINPUT_DEVICE_CAP_TOUCH: return device->touch; case LIBINPUT_DEVICE_CAP_GESTURE: return device->gestureSupported; +#if HAVE_LIBINPUT_1_2 + case LIBINPUT_DEVICE_CAP_TABLET_TOOL: + return device->tabletTool; +#endif default: return 0; } } const char *libinput_device_get_name(struct libinput_device *device) { return device->name.constData(); } const char *libinput_device_get_sysname(struct libinput_device *device) { return device->sysName.constData(); } const char *libinput_device_get_output_name(struct libinput_device *device) { return device->outputName.constData(); } unsigned int libinput_device_get_id_product(struct libinput_device *device) { return device->product; } unsigned int libinput_device_get_id_vendor(struct libinput_device *device) { return device->vendor; } int libinput_device_config_tap_get_finger_count(struct libinput_device *device) { return device->tapFingerCount; } enum libinput_config_tap_state libinput_device_config_tap_get_enabled(struct libinput_device *device) { Q_UNUSED(device) return LIBINPUT_CONFIG_TAP_DISABLED; } enum libinput_config_tap_state libinput_device_config_tap_get_default_enabled(struct libinput_device *device) { if (device->tapEnabledByDefault) { return LIBINPUT_CONFIG_TAP_ENABLED; } else { return LIBINPUT_CONFIG_TAP_DISABLED; } } int libinput_device_config_dwt_is_available(struct libinput_device *device) { return device->supportsDisableWhileTyping; } int libinput_device_config_accel_is_available(struct libinput_device *device) { return device->supportsPointerAcceleration; } int libinput_device_config_calibration_has_matrix(struct libinput_device *device) { return device->supportsCalibrationMatrix; } int libinput_device_config_left_handed_is_available(struct libinput_device *device) { return device->supportsLeftHanded; } uint32_t libinput_device_config_send_events_get_modes(struct libinput_device *device) { uint32_t modes = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; if (device->supportsDisableEvents) { modes |= LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; } if (device->supportsDisableEventsOnExternalMouse) { modes |= LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE; } return modes; } int libinput_device_config_left_handed_get(struct libinput_device *device) { return device->leftHanded; } double libinput_device_config_accel_get_speed(struct libinput_device *device) { return device->pointerAcceleration; } uint32_t libinput_device_config_send_events_get_mode(struct libinput_device *device) { if (device->enabled) { return LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; } else { // TODO: disabled on eternal mouse return LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; } } struct libinput_device *libinput_device_ref(struct libinput_device *device) { return device; } struct libinput_device *libinput_device_unref(struct libinput_device *device) { return device; } int libinput_device_get_size(struct libinput_device *device, double *width, double *height) { if (device->deviceSizeReturnValue) { return device->deviceSizeReturnValue; } if (width) { *width = device->deviceSize.width(); } if (height) { *height = device->deviceSize.height(); } return device->deviceSizeReturnValue; } int libinput_device_pointer_has_button(struct libinput_device *device, uint32_t code) { switch (code) { case BTN_LEFT: return device->supportedButtons.testFlag(Qt::LeftButton); case BTN_MIDDLE: return device->supportedButtons.testFlag(Qt::MiddleButton); case BTN_RIGHT: return device->supportedButtons.testFlag(Qt::RightButton); case BTN_SIDE: return device->supportedButtons.testFlag(Qt::ExtraButton1); case BTN_EXTRA: return device->supportedButtons.testFlag(Qt::ExtraButton2); case BTN_BACK: return device->supportedButtons.testFlag(Qt::BackButton); case BTN_FORWARD: return device->supportedButtons.testFlag(Qt::ForwardButton); case BTN_TASK: return device->supportedButtons.testFlag(Qt::TaskButton); default: return 0; } } enum libinput_config_status libinput_device_config_left_handed_set(struct libinput_device *device, int left_handed) { if (device->setLeftHandedReturnValue == 0) { device->leftHanded = left_handed; return LIBINPUT_CONFIG_STATUS_SUCCESS; } return LIBINPUT_CONFIG_STATUS_INVALID; } enum libinput_config_status libinput_device_config_accel_set_speed(struct libinput_device *device, double speed) { if (device->setPointerAccelerationReturnValue == 0) { device->pointerAcceleration = speed; return LIBINPUT_CONFIG_STATUS_SUCCESS; } return LIBINPUT_CONFIG_STATUS_INVALID; } enum libinput_config_status libinput_device_config_send_events_set_mode(struct libinput_device *device, uint32_t mode) { if (device->setEnableModeReturnValue == 0) { device->enabled = (mode == LIBINPUT_CONFIG_SEND_EVENTS_ENABLED); return LIBINPUT_CONFIG_STATUS_SUCCESS; } return LIBINPUT_CONFIG_STATUS_INVALID; } enum libinput_event_type libinput_event_get_type(struct libinput_event *event) { return event->type; } struct libinput_device *libinput_event_get_device(struct libinput_event *event) { return event->device; } void libinput_event_destroy(struct libinput_event *event) { delete event; } struct libinput_event_keyboard *libinput_event_get_keyboard_event(struct libinput_event *event) { if (event->type == LIBINPUT_EVENT_KEYBOARD_KEY) { return reinterpret_cast(event); } return nullptr; } struct libinput_event_pointer *libinput_event_get_pointer_event(struct libinput_event *event) { if (event->type == LIBINPUT_EVENT_POINTER_MOTION || event->type == LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE || event->type == LIBINPUT_EVENT_POINTER_BUTTON || event->type == LIBINPUT_EVENT_POINTER_AXIS) { return reinterpret_cast(event); } return nullptr; } struct libinput_event_touch *libinput_event_get_touch_event(struct libinput_event *event) { if (event->type == LIBINPUT_EVENT_TOUCH_DOWN || event->type == LIBINPUT_EVENT_TOUCH_UP || event->type == LIBINPUT_EVENT_TOUCH_MOTION || event->type == LIBINPUT_EVENT_TOUCH_CANCEL || event->type == LIBINPUT_EVENT_TOUCH_FRAME) { return reinterpret_cast(event); } return nullptr; } uint32_t libinput_event_keyboard_get_key(struct libinput_event_keyboard *event) { return event->key; } enum libinput_key_state libinput_event_keyboard_get_key_state(struct libinput_event_keyboard *event) { return event->state; } uint32_t libinput_event_keyboard_get_time(struct libinput_event_keyboard *event) { return event->time; } double libinput_event_pointer_get_absolute_x(struct libinput_event_pointer *event) { return event->absolutePos.x(); } double libinput_event_pointer_get_absolute_y(struct libinput_event_pointer *event) { return event->absolutePos.y(); } double libinput_event_pointer_get_absolute_x_transformed(struct libinput_event_pointer *event, uint32_t width) { double deviceWidth = 0.0; double deviceHeight = 0.0; libinput_device_get_size(event->device, &deviceWidth, &deviceHeight); return event->absolutePos.x() / deviceWidth * width; } double libinput_event_pointer_get_absolute_y_transformed(struct libinput_event_pointer *event, uint32_t height) { double deviceWidth = 0.0; double deviceHeight = 0.0; libinput_device_get_size(event->device, &deviceWidth, &deviceHeight); return event->absolutePos.y() / deviceHeight * height; } double libinput_event_pointer_get_dx(struct libinput_event_pointer *event) { return event->delta.width(); } double libinput_event_pointer_get_dy(struct libinput_event_pointer *event) { return event->delta.height(); } uint32_t libinput_event_pointer_get_time(struct libinput_event_pointer *event) { return event->time; } uint32_t libinput_event_pointer_get_button(struct libinput_event_pointer *event) { return event->button; } enum libinput_button_state libinput_event_pointer_get_button_state(struct libinput_event_pointer *event) { return event->buttonState; } int libinput_event_pointer_has_axis(struct libinput_event_pointer *event, enum libinput_pointer_axis axis) { if (axis == LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL) { return event->verticalAxis; } else { return event->horizontalAxis; } } double libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event, enum libinput_pointer_axis axis) { if (axis == LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL) { return event->verticalAxisValue; } else { return event->horizontalAxisValue; } } uint32_t libinput_event_touch_get_time(struct libinput_event_touch *event) { return event->time; } double libinput_event_touch_get_x(struct libinput_event_touch *event) { return event->absolutePos.x(); } double libinput_event_touch_get_y(struct libinput_event_touch *event) { return event->absolutePos.y(); } double libinput_event_touch_get_x_transformed(struct libinput_event_touch *event, uint32_t width) { double deviceWidth = 0.0; double deviceHeight = 0.0; libinput_device_get_size(event->device, &deviceWidth, &deviceHeight); return event->absolutePos.x() / deviceWidth * width; } double libinput_event_touch_get_y_transformed(struct libinput_event_touch *event, uint32_t height) { double deviceWidth = 0.0; double deviceHeight = 0.0; libinput_device_get_size(event->device, &deviceWidth, &deviceHeight); return event->absolutePos.y() / deviceHeight * height; } int32_t libinput_event_touch_get_slot(struct libinput_event_touch *event) { return event->slot; } struct libinput *libinput_udev_create_context(const struct libinput_interface *interface, void *user_data, struct udev *udev) { if (!udev) { return nullptr; } Q_UNUSED(interface) Q_UNUSED(user_data) return new libinput; } void libinput_log_set_priority(struct libinput *libinput, enum libinput_log_priority priority) { Q_UNUSED(libinput) Q_UNUSED(priority) } void libinput_log_set_handler(struct libinput *libinput, libinput_log_handler log_handler) { Q_UNUSED(libinput) Q_UNUSED(log_handler) } struct libinput *libinput_unref(struct libinput *libinput) { libinput->refCount--; if (libinput->refCount == 0) { delete libinput; return nullptr; } return libinput; } int libinput_udev_assign_seat(struct libinput *libinput, const char *seat_id) { if (libinput->assignSeatRetVal == 0) { libinput->seat = QByteArray(seat_id); } return libinput->assignSeatRetVal; } int libinput_get_fd(struct libinput *libinput) { Q_UNUSED(libinput) return -1; } int libinput_dispatch(struct libinput *libinput) { Q_UNUSED(libinput) return 0; } struct libinput_event *libinput_get_event(struct libinput *libinput) { Q_UNUSED(libinput) return nullptr; } void libinput_suspend(struct libinput *libinput) { Q_UNUSED(libinput) } int libinput_resume(struct libinput *libinput) { Q_UNUSED(libinput) return 0; } diff --git a/autotests/libinput/mock_libinput.h b/autotests/libinput/mock_libinput.h index a6cfedc43..6779dc535 100644 --- a/autotests/libinput/mock_libinput.h +++ b/autotests/libinput/mock_libinput.h @@ -1,95 +1,96 @@ /******************************************************************** 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 . *********************************************************************/ #ifndef MOCK_LIBINPUT_H #define MOCK_LIBINPUT_H #include #include #include #include #include struct libinput_device { bool keyboard = false; bool pointer = false; bool touch = false; + bool tabletTool = false; bool gestureSupported = false; QByteArray name; QByteArray sysName; QByteArray outputName; quint32 product = 0; quint32 vendor = 0; int tapFingerCount = 0; QSizeF deviceSize; int deviceSizeReturnValue = 0; bool tapEnabledByDefault = false; bool supportsDisableWhileTyping = false; bool supportsPointerAcceleration = false; bool supportsLeftHanded = false; bool supportsCalibrationMatrix = false; bool supportsDisableEvents = false; bool supportsDisableEventsOnExternalMouse = false; qreal pointerAcceleration = 0.0; int setPointerAccelerationReturnValue = 0; bool leftHanded = false; int setLeftHandedReturnValue = 0; Qt::MouseButtons supportedButtons; QVector keys; bool enabled = true; int setEnableModeReturnValue = 0; }; struct libinput_event { libinput_device *device = nullptr; libinput_event_type type = LIBINPUT_EVENT_NONE; quint32 time = 0; }; struct libinput_event_keyboard : libinput_event { libinput_event_keyboard() { type = LIBINPUT_EVENT_KEYBOARD_KEY; } libinput_key_state state = LIBINPUT_KEY_STATE_RELEASED; quint32 key = 0; }; struct libinput_event_pointer : libinput_event { libinput_button_state buttonState = LIBINPUT_BUTTON_STATE_RELEASED; quint32 button = 0; bool verticalAxis = false; bool horizontalAxis = false; qreal horizontalAxisValue = 0.0; qreal verticalAxisValue = 0.0; QSizeF delta; QPointF absolutePos; }; struct libinput_event_touch : libinput_event { qint32 slot = -1; QPointF absolutePos; }; struct libinput { int refCount = 1; QByteArray seat; int assignSeatRetVal = 0; }; #endif diff --git a/config-kwin.h.cmake b/config-kwin.h.cmake index 56e5c47e6..9beff77e5 100644 --- a/config-kwin.h.cmake +++ b/config-kwin.h.cmake @@ -1,40 +1,41 @@ #cmakedefine KWIN_BUILD_DECORATIONS 1 #cmakedefine KWIN_BUILD_TABBOX 1 #cmakedefine KWIN_BUILD_ACTIVITIES 1 #define KWIN_NAME "${KWIN_NAME}" #define KWIN_INTERNAL_NAME_X11 "${KWIN_INTERNAL_NAME_X11}" #define KWIN_CONFIG "${KWIN_NAME}rc" #define KWIN_VERSION_STRING "${PROJECT_VERSION}" #define XCB_VERSION_STRING "${XCB_VERSION}" #define KWIN_KILLER_BIN "${CMAKE_INSTALL_FULL_LIBEXECDIR}/kwin_killer_helper" #define KWIN_RULES_DIALOG_BIN "${CMAKE_INSTALL_FULL_LIBEXECDIR}/kwin_rules_dialog" #define KWIN_XCLIPBOARD_SYNC_BIN "${CMAKE_INSTALL_FULL_LIBEXECDIR}/org_kde_kwin_xclipboard_syncer" #cmakedefine01 HAVE_INPUT +#cmakedefine01 HAVE_LIBINPUT_1_2 #cmakedefine01 HAVE_X11_XCB #cmakedefine01 HAVE_X11_XINPUT #cmakedefine01 HAVE_DRM #cmakedefine01 HAVE_GBM #cmakedefine01 HAVE_LIBHYBRIS #cmakedefine01 HAVE_WAYLAND_EGL #cmakedefine01 HAVE_SYS_PRCTL_H #cmakedefine01 HAVE_PR_SET_DUMPABLE #cmakedefine01 HAVE_SYS_PROCCTL_H #cmakedefine01 HAVE_PROC_TRACE_CTL #cmakedefine01 HAVE_BREEZE_DECO #cmakedefine01 HAVE_UDEV #if HAVE_BREEZE_DECO #define BREEZE_KDECORATION_PLUGIN_ID "${BREEZE_KDECORATION_PLUGIN_ID}" #endif /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UNISTD_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_MALLOC_H 1 #cmakedefine XCB_ICCCM_FOUND 1 #ifndef XCB_ICCCM_FOUND #define XCB_ICCCM_WM_STATE_WITHDRAWN 0 #define XCB_ICCCM_WM_STATE_NORMAL 1 #define XCB_ICCCM_WM_STATE_ICONIC 3 #endif diff --git a/libinput/device.cpp b/libinput/device.cpp index f996fd31d..08af97452 100644 --- a/libinput/device.cpp +++ b/libinput/device.cpp @@ -1,189 +1,194 @@ /******************************************************************** 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 "device.h" #include #include +#include + namespace KWin { namespace LibInput { static bool checkAlphaNumericKeyboard(libinput_device *device) { for (uint i = KEY_1; i <= KEY_0; i++) { if (libinput_device_keyboard_has_key(device, i) == 0) { return false; } } for (uint i = KEY_Q; i <= KEY_P; i++) { if (libinput_device_keyboard_has_key(device, i) == 0) { return false; } } for (uint i = KEY_A; i <= KEY_L; i++) { if (libinput_device_keyboard_has_key(device, i) == 0) { return false; } } for (uint i = KEY_Z; i <= KEY_M; i++) { if (libinput_device_keyboard_has_key(device, i) == 0) { return false; } } return true; } QVector Device::s_devices; Device *Device::getDevice(libinput_device *native) { auto it = std::find_if(s_devices.constBegin(), s_devices.constEnd(), [native] (const Device *d) { return d->device() == native; } ); if (it != s_devices.constEnd()) { return *it; } return nullptr; } Device::Device(libinput_device *device, QObject *parent) : QObject(parent) , m_device(device) , m_keyboard(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_KEYBOARD)) , m_pointer(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_POINTER)) , m_touch(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_TOUCH)) +#if HAVE_LIBINPUT_1_2 + , m_tabletTool(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) +#else + , m_tabletTool(false) +#endif #if 0 // next libinput version - , m_tabletTool(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) , m_tabletPad(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_TABLET_PAD)) #else - , m_tabletTool(false) , m_tabletPad(false) #endif , m_supportsGesture(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_GESTURE)) , m_name(QString::fromLocal8Bit(libinput_device_get_name(m_device))) , m_sysName(QString::fromLocal8Bit(libinput_device_get_sysname(m_device))) , m_outputName(QString::fromLocal8Bit(libinput_device_get_output_name(m_device))) , m_product(libinput_device_get_id_product(m_device)) , m_vendor(libinput_device_get_id_vendor(m_device)) , m_tapFingerCount(libinput_device_config_tap_get_finger_count(m_device)) , m_tapEnabledByDefault(libinput_device_config_tap_get_default_enabled(m_device) == LIBINPUT_CONFIG_TAP_ENABLED) , m_supportsDisableWhileTyping(libinput_device_config_dwt_is_available(m_device)) , m_supportsPointerAcceleration(libinput_device_config_accel_is_available(m_device)) , m_supportsLeftHanded(libinput_device_config_left_handed_is_available(m_device)) , m_supportsCalibrationMatrix(libinput_device_config_calibration_has_matrix(m_device)) , m_supportsDisableEvents(libinput_device_config_send_events_get_modes(m_device) & LIBINPUT_CONFIG_SEND_EVENTS_DISABLED) , m_supportsDisableEventsOnExternalMouse(libinput_device_config_send_events_get_modes(m_device) & LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE) , m_leftHanded(m_supportsLeftHanded ? libinput_device_config_left_handed_get(m_device) : false) , m_pointerAcceleration(libinput_device_config_accel_get_speed(m_device)) , m_enabled(m_supportsDisableEvents ? libinput_device_config_send_events_get_mode(m_device) == LIBINPUT_CONFIG_SEND_EVENTS_ENABLED : true) { libinput_device_ref(m_device); qreal width = 0; qreal height = 0; if (libinput_device_get_size(m_device, &width, &height) == 0) { m_size = QSizeF(width, height); } if (m_pointer) { if (libinput_device_pointer_has_button(m_device, BTN_LEFT) == 1) { m_supportedButtons |= Qt::LeftButton; } if (libinput_device_pointer_has_button(m_device, BTN_MIDDLE) == 1) { m_supportedButtons |= Qt::MiddleButton; } if (libinput_device_pointer_has_button(m_device, BTN_RIGHT) == 1) { m_supportedButtons |= Qt::RightButton; } if (libinput_device_pointer_has_button(m_device, BTN_SIDE) == 1) { m_supportedButtons |= Qt::ExtraButton1; } if (libinput_device_pointer_has_button(m_device, BTN_EXTRA) == 1) { m_supportedButtons |= Qt::ExtraButton2; } if (libinput_device_pointer_has_button(m_device, BTN_BACK) == 1) { m_supportedButtons |= Qt::BackButton; } if (libinput_device_pointer_has_button(m_device, BTN_FORWARD) == 1) { m_supportedButtons |= Qt::ForwardButton; } if (libinput_device_pointer_has_button(m_device, BTN_TASK) == 1) { m_supportedButtons |= Qt::TaskButton; } } if (m_keyboard) { m_alphaNumericKeyboard = checkAlphaNumericKeyboard(m_device); } s_devices << this; } Device::~Device() { s_devices.removeOne(this); libinput_device_unref(m_device); } void Device::setLeftHanded(bool set) { if (!m_supportsLeftHanded) { return; } if (libinput_device_config_left_handed_set(m_device, set) == LIBINPUT_CONFIG_STATUS_SUCCESS) { if (m_leftHanded != set) { m_leftHanded = set; emit leftHandedChanged(); } } } void Device::setPointerAcceleration(qreal acceleration) { if (!m_supportsPointerAcceleration) { return; } acceleration = qBound(-1.0, acceleration, 1.0); if (libinput_device_config_accel_set_speed(m_device, acceleration) == LIBINPUT_CONFIG_STATUS_SUCCESS) { if (m_pointerAcceleration != acceleration) { m_pointerAcceleration = acceleration; emit pointerAccelerationChanged(); } } } void Device::setEnabled(bool enabled) { if (!m_supportsDisableEvents) { return; } if (libinput_device_config_send_events_set_mode(m_device, enabled ? LIBINPUT_CONFIG_SEND_EVENTS_ENABLED : LIBINPUT_CONFIG_SEND_EVENTS_DISABLED) == LIBINPUT_CONFIG_STATUS_SUCCESS) { if (m_enabled != enabled) { m_enabled = enabled; emit enabledChanged(); } } } } }