diff --git a/autotests/kwindoweffectstest.cpp b/autotests/kwindoweffectstest.cpp index 089001b..80b7ccd 100644 --- a/autotests/kwindoweffectstest.cpp +++ b/autotests/kwindoweffectstest.cpp @@ -1,465 +1,471 @@ /* * Copyright 2013 Martin Gräßlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include #include #include #include #include #include #include #include Q_DECLARE_METATYPE(KWindowEffects::SlideFromLocation) Q_DECLARE_METATYPE(KWindowEffects::Effect) class KWindowEffectsTest : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void testSlideWindow_data(); void testSlideWindow(); void testSlideWindowRemove(); void testSlideWindowWidget_data(); void testSlideWindowWidget(); void testSlideWindowWidgetRemove(); void testPresentWindows_data(); void testPresentWindows(); void testPresentWindowsEmptyGroup(); void testPresentWindowsGroup_data(); void testPresentWindowsGroup(); void testHighlightWindows_data(); void testHighlightWindows(); void testHighlightWindowsEmpty(); void testBlur_data(); void testBlur(); void testBlurDisable(); +#if KWINDOWSYSTEM_ENABLE_DEPRECATED_SINCE(5, 67) void testMarkAsDashboard(); +#endif void testEffectAvailable_data(); void testEffectAvailable(); private: int32_t locationToValue(KWindowEffects::SlideFromLocation location) const; void performSlideWindowTest(xcb_window_t window, int offset, KWindowEffects::SlideFromLocation location) const; void performSlideWindowRemoveTest(xcb_window_t window); void performWindowsOnPropertyTest(xcb_atom_t atom, const QList &windows); void performAtomIsRemoveTest(xcb_window_t window, xcb_atom_t atom); void getHelperAtom(const QByteArray &name, xcb_atom_t *atom) const; xcb_atom_t m_slide; xcb_atom_t m_presentWindows; xcb_atom_t m_presentWindowsGroup; xcb_atom_t m_highlightWindows; xcb_atom_t m_thumbnails; xcb_atom_t m_blur; QScopedPointer m_window; QScopedPointer m_widget; }; void KWindowEffectsTest::initTestCase() { m_window.reset(new QWindow()); QVERIFY(m_window->winId() != XCB_WINDOW_NONE); m_widget.reset(new QWidget()); m_widget->show(); QVERIFY(m_widget->effectiveWinId() != XCB_WINDOW_NONE); getHelperAtom(QByteArrayLiteral("_KDE_SLIDE"), &m_slide); getHelperAtom(QByteArrayLiteral("_KDE_PRESENT_WINDOWS_DESKTOP"), &m_presentWindows); getHelperAtom(QByteArrayLiteral("_KDE_PRESENT_WINDOWS_GROUP"), &m_presentWindowsGroup); getHelperAtom(QByteArrayLiteral("_KDE_WINDOW_HIGHLIGHT"), &m_highlightWindows); getHelperAtom(QByteArrayLiteral("_KDE_WINDOW_PREVIEW"), &m_thumbnails); getHelperAtom(QByteArrayLiteral("_KDE_NET_WM_BLUR_BEHIND_REGION"), &m_blur); } void KWindowEffectsTest::getHelperAtom(const QByteArray &name, xcb_atom_t *atom) const { xcb_connection_t *c = QX11Info::connection(); xcb_intern_atom_cookie_t atomCookie = xcb_intern_atom_unchecked(c, false, name.length(), name.constData()); QScopedPointer reply(xcb_intern_atom_reply(c, atomCookie, nullptr)); QVERIFY(!reply.isNull()); *atom = reply->atom; } void KWindowEffectsTest::testSlideWindow_data() { QTest::addColumn("offset"); QTest::addColumn("location"); QTest::newRow("Left") << 10 << KWindowEffects::LeftEdge; QTest::newRow("Right") << 20 << KWindowEffects::RightEdge; QTest::newRow("Top") << 0 << KWindowEffects::TopEdge; QTest::newRow("Bottom") << -1 << KWindowEffects::BottomEdge; } void KWindowEffectsTest::testSlideWindow() { QFETCH(int, offset); QFETCH(KWindowEffects::SlideFromLocation, location); KWindowEffects::slideWindow(m_window->winId(), location, offset); performSlideWindowTest(m_window->winId(), offset, location); } void KWindowEffectsTest::testSlideWindowRemove() { xcb_window_t window = m_window->winId(); // first install the atom KWindowEffects::slideWindow(window, KWindowEffects::TopEdge, 0); performSlideWindowTest(window, 0, KWindowEffects::TopEdge); // now delete it KWindowEffects::slideWindow(window, KWindowEffects::NoEdge, 0); performSlideWindowRemoveTest(window); } void KWindowEffectsTest::testSlideWindowWidget_data() { QTest::addColumn("location"); QTest::newRow("Left") << KWindowEffects::LeftEdge; QTest::newRow("Right") << KWindowEffects::RightEdge; QTest::newRow("Top") << KWindowEffects::TopEdge; QTest::newRow("Bottom") << KWindowEffects::BottomEdge; } void KWindowEffectsTest::testSlideWindowWidget() { QFETCH(KWindowEffects::SlideFromLocation, location); KWindowEffects::slideWindow(m_widget->effectiveWinId(), location); performSlideWindowTest(m_widget->effectiveWinId(), -1, location); } void KWindowEffectsTest::testSlideWindowWidgetRemove() { xcb_window_t window = m_widget->effectiveWinId(); // first install the atom KWindowEffects::slideWindow(m_widget->effectiveWinId(), KWindowEffects::TopEdge); performSlideWindowTest(window, -1, KWindowEffects::TopEdge); // now delete it KWindowEffects::slideWindow(m_widget->effectiveWinId(), KWindowEffects::NoEdge); performSlideWindowRemoveTest(window); } void KWindowEffectsTest::performSlideWindowTest(xcb_window_t window, int offset, KWindowEffects::SlideFromLocation location) const { xcb_connection_t *c = QX11Info::connection(); xcb_get_property_cookie_t cookie = xcb_get_property_unchecked(c, false, window, m_slide, m_slide, 0, 100); QScopedPointer reply(xcb_get_property_reply(c, cookie, nullptr)); QVERIFY(!reply.isNull()); QCOMPARE(reply->format, uint8_t(32)); QCOMPARE(reply->value_len, uint32_t(2)); QCOMPARE(reply->type, m_slide); int32_t *data = static_cast(xcb_get_property_value(reply.data())); QCOMPARE(data[0], offset); QCOMPARE(data[1], locationToValue(location)); } void KWindowEffectsTest::performSlideWindowRemoveTest(xcb_window_t window) { performAtomIsRemoveTest(window, m_slide); } void KWindowEffectsTest::performAtomIsRemoveTest(xcb_window_t window, xcb_atom_t atom) { xcb_connection_t *c = QX11Info::connection(); xcb_get_property_cookie_t cookie = xcb_get_property_unchecked(c, false, window, atom, atom, 0, 100); QScopedPointer reply(xcb_get_property_reply(c, cookie, nullptr)); QVERIFY(!reply.isNull()); QCOMPARE(reply->type, xcb_atom_t(XCB_ATOM_NONE)); } int32_t KWindowEffectsTest::locationToValue(KWindowEffects::SlideFromLocation location) const { switch (location) { case KWindowEffects::LeftEdge: return 0; case KWindowEffects::TopEdge: return 1; case KWindowEffects::RightEdge: return 2; case KWindowEffects::BottomEdge: return 3; default: return -1; } } void KWindowEffectsTest::testPresentWindows_data() { QTest::addColumn("desktop"); QTest::newRow("all desktops") << -1; QTest::newRow("1") << 1; QTest::newRow("2") << 2; QTest::newRow("3") << 3; QTest::newRow("4") << 4; } void KWindowEffectsTest::testPresentWindows() { QFETCH(int, desktop); KWindowEffects::presentWindows(m_window->winId(), desktop); xcb_connection_t *c = QX11Info::connection(); xcb_get_property_cookie_t cookie = xcb_get_property_unchecked(c, false, m_window->winId(), m_presentWindows, m_presentWindows, 0, 100); QScopedPointer reply(xcb_get_property_reply(c, cookie, nullptr)); QVERIFY(!reply.isNull()); QCOMPARE(reply->format, uint8_t(32)); QCOMPARE(reply->value_len, uint32_t(1)); QCOMPARE(reply->type, m_presentWindows); int32_t *data = static_cast(xcb_get_property_value(reply.data())); QCOMPARE(data[0], desktop); } void KWindowEffectsTest::testPresentWindowsEmptyGroup() { KWindowEffects::presentWindows(m_window->winId(), QList()); xcb_connection_t *c = QX11Info::connection(); xcb_get_property_cookie_t cookie = xcb_get_property_unchecked(c, false, m_window->winId(), m_presentWindowsGroup, m_presentWindowsGroup, 0, 100); QScopedPointer reply(xcb_get_property_reply(c, cookie, nullptr)); QVERIFY(!reply.isNull()); QCOMPARE(reply->type, xcb_atom_t(XCB_ATOM_NONE)); } void KWindowEffectsTest::testPresentWindowsGroup_data() { QTest::addColumn >("windows"); QTest::newRow("one") << (QList() << m_window->winId()); QTest::newRow("two") << (QList() << m_window->winId() << m_widget->effectiveWinId()); } void KWindowEffectsTest::testPresentWindowsGroup() { QFETCH(QList, windows); KWindowEffects::presentWindows(m_window->winId(), windows); performWindowsOnPropertyTest(m_presentWindowsGroup, windows); } void KWindowEffectsTest::testHighlightWindows_data() { QTest::addColumn >("windows"); QTest::newRow("one") << (QList() << m_window->winId()); QTest::newRow("two") << (QList() << m_window->winId() << m_widget->effectiveWinId()); } void KWindowEffectsTest::testHighlightWindows() { QFETCH(QList, windows); KWindowEffects::highlightWindows(m_window->winId(), windows); performWindowsOnPropertyTest(m_highlightWindows, windows); } void KWindowEffectsTest::testHighlightWindowsEmpty() { // ensure it's empty KWindowEffects::highlightWindows(m_window->winId(), QList()); performAtomIsRemoveTest(m_window->winId(), m_highlightWindows); // install some windows on the atom QList windows; windows.append(m_window->winId()); windows.append(m_widget->effectiveWinId()); KWindowEffects::highlightWindows(m_window->winId(), windows); performWindowsOnPropertyTest(m_highlightWindows, windows); // and remove it again KWindowEffects::highlightWindows(m_window->winId(), QList()); performAtomIsRemoveTest(m_window->winId(), m_highlightWindows); } void KWindowEffectsTest::performWindowsOnPropertyTest(xcb_atom_t atom, const QList< WId > &windows) { xcb_connection_t *c = QX11Info::connection(); xcb_get_property_cookie_t cookie = xcb_get_property_unchecked(c, false, m_window->winId(), atom, atom, 0, 100); QScopedPointer reply(xcb_get_property_reply(c, cookie, nullptr)); QVERIFY(!reply.isNull()); QCOMPARE(reply->type, atom); QCOMPARE(reply->format, uint8_t(32)); QCOMPARE(reply->value_len, uint32_t(windows.size())); int32_t *data = static_cast(xcb_get_property_value(reply.data())); for (int i = 0; i < windows.size(); ++i) { QCOMPARE(data[i], int32_t(windows.at(i))); } } void KWindowEffectsTest::testBlur_data() { QTest::addColumn("blur"); QRegion region(0, 0, 10, 10); QTest::newRow("one rect") << region; region = region.united(QRect(20, 20, 5, 5)); QTest::newRow("two rects") << region; region = region.united(QRect(100, 100, 20, 20)); QTest::newRow("three rects") << region; QTest::newRow("empty") << QRegion(); } void KWindowEffectsTest::testBlur() { QFETCH(QRegion, blur); KWindowEffects::enableBlurBehind(m_window->winId(), true, blur); xcb_connection_t *c = QX11Info::connection(); xcb_get_property_cookie_t cookie = xcb_get_property_unchecked(c, false, m_window->winId(), m_blur, XCB_ATOM_CARDINAL, 0, 100); QScopedPointer reply(xcb_get_property_reply(c, cookie, nullptr)); QVERIFY(!reply.isNull()); QCOMPARE(reply->type, xcb_atom_t(XCB_ATOM_CARDINAL)); QCOMPARE(reply->format, uint8_t(32)); QCOMPARE(reply->value_len, uint32_t(blur.rectCount() * 4)); uint32_t *data = static_cast(xcb_get_property_value(reply.data())); int dataOffset = 0; for (const QRect& rect : blur) { QCOMPARE(data[dataOffset++], uint32_t(rect.x())); QCOMPARE(data[dataOffset++], uint32_t(rect.y())); QCOMPARE(data[dataOffset++], uint32_t(rect.width())); QCOMPARE(data[dataOffset++], uint32_t(rect.height())); } } void KWindowEffectsTest::testBlurDisable() { KWindowEffects::enableBlurBehind(m_window->winId(), false); performAtomIsRemoveTest(m_window->winId(), m_blur); KWindowEffects::enableBlurBehind(m_window->winId(), true); //verify that it got added xcb_connection_t *c = QX11Info::connection(); xcb_get_property_cookie_t cookie = xcb_get_property_unchecked(c, false, m_window->winId(), m_blur, XCB_ATOM_CARDINAL, 0, 100); QScopedPointer reply(xcb_get_property_reply(c, cookie, nullptr)); QVERIFY(!reply.isNull()); QCOMPARE(reply->type, xcb_atom_t(XCB_ATOM_CARDINAL)); // and disable KWindowEffects::enableBlurBehind(m_window->winId(), false); performAtomIsRemoveTest(m_window->winId(), m_blur); } +#if KWINDOWSYSTEM_ENABLE_DEPRECATED_SINCE(5, 67) void KWindowEffectsTest::testMarkAsDashboard() { const QByteArray className = QByteArrayLiteral("dashboard"); // should not yet be set xcb_connection_t *c = QX11Info::connection(); xcb_get_property_cookie_t cookie = xcb_get_property_unchecked(c, false, m_window->winId(), XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 0, 100); QScopedPointer reply(xcb_get_property_reply(c, cookie, nullptr)); QVERIFY(!reply.isNull()); QCOMPARE(reply->type, xcb_atom_t(XCB_ATOM_STRING)); QCOMPARE(reply->format, uint8_t(8)); char *data = static_cast(xcb_get_property_value(reply.data())); QVERIFY(QByteArray(data) != className); // now mark as dashboard KWindowEffects::markAsDashboard(m_window->winId()); cookie = xcb_get_property_unchecked(c, false, m_window->winId(), XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 0, 100); reply.reset(xcb_get_property_reply(c, cookie, nullptr)); QVERIFY(!reply.isNull()); QCOMPARE(reply->type, xcb_atom_t(XCB_ATOM_STRING)); QCOMPARE(reply->format, uint8_t(8)); QCOMPARE(reply->value_len, uint32_t(19)); data = static_cast(xcb_get_property_value(reply.data())); QCOMPARE(QByteArray(data), className); data = data + 10; QCOMPARE(QByteArray(data), className); } +#endif void KWindowEffectsTest::testEffectAvailable_data() { QTest::addColumn("effect"); QTest::addColumn("propertyName"); QTest::newRow("slide") << KWindowEffects::Slide << QByteArrayLiteral("_KDE_SLIDE"); QTest::newRow("PresentWindows") << KWindowEffects::PresentWindows << QByteArrayLiteral("_KDE_PRESENT_WINDOWS_DESKTOP"); QTest::newRow("PresentWindowsGroup") << KWindowEffects::PresentWindowsGroup << QByteArrayLiteral("_KDE_PRESENT_WINDOWS_GROUP"); QTest::newRow("HighlightWindows") << KWindowEffects::HighlightWindows << QByteArrayLiteral("_KDE_WINDOW_HIGHLIGHT"); QTest::newRow("BlurBehind") << KWindowEffects::BlurBehind << QByteArrayLiteral("_KDE_NET_WM_BLUR_BEHIND_REGION"); +#if KWINDOWSYSTEM_ENABLE_DEPRECATED_SINCE(5, 67) QTest::newRow("Dashboard") << KWindowEffects::Dashboard << QByteArrayLiteral("_WM_EFFECT_KDE_DASHBOARD"); +#endif QTest::newRow("BackgroundContrast") << KWindowEffects::BackgroundContrast << QByteArrayLiteral("_KDE_NET_WM_BACKGROUND_CONTRAST_REGION"); } void KWindowEffectsTest::testEffectAvailable() { NETRootInfo rootInfo(QX11Info::connection(), NET::Supported | NET::SupportingWMCheck); if (qstrcmp(rootInfo.wmName(), "KWin") == 0) { QSKIP("KWin running, we don't want to interact with the running system"); } // this test verifies whether an effect is available QFETCH(KWindowEffects::Effect, effect); // without a compositing manager it's not available // try-verify as there still might be the selection claimed from previous data run QTRY_VERIFY(!KWindowSystem::compositingActive()); QVERIFY(!KWindowEffects::isEffectAvailable(effect)); // fake the compositor QSignalSpy compositingChangedSpy(KWindowSystem::self(), &KWindowSystem::compositingChanged); QVERIFY(compositingChangedSpy.isValid()); KSelectionOwner compositorSelection("_NET_WM_CM_S0"); QSignalSpy claimedSpy(&compositorSelection, &KSelectionOwner::claimedOwnership); QVERIFY(claimedSpy.isValid()); compositorSelection.claim(true); QVERIFY(claimedSpy.wait()); QCOMPARE(compositingChangedSpy.count(), 1); QCOMPARE(compositingChangedSpy.first().first().toBool(), true); QVERIFY(KWindowSystem::compositingActive()); // but not yet available QVERIFY(!KWindowEffects::isEffectAvailable(effect)); // set the atom QFETCH(QByteArray, propertyName); xcb_connection_t *c = QX11Info::connection(); xcb_intern_atom_cookie_t atomCookie = xcb_intern_atom_unchecked(c, false, propertyName.length(), propertyName.constData()); QScopedPointer atom(xcb_intern_atom_reply(c, atomCookie, nullptr)); QVERIFY(!atom.isNull()); unsigned char dummy = 0; xcb_change_property(c, XCB_PROP_MODE_REPLACE, QX11Info::appRootWindow(), atom->atom, atom->atom, 8, 1, &dummy); xcb_flush(c); // now the effect should be available QVERIFY(KWindowEffects::isEffectAvailable(effect)); // delete the property again xcb_delete_property(c, QX11Info::appRootWindow(), atom->atom); xcb_flush(c); // which means it's no longer available QVERIFY(!KWindowEffects::isEffectAvailable(effect)); // remove compositing selection compositorSelection.release(); QVERIFY(compositingChangedSpy.wait()); QCOMPARE(compositingChangedSpy.count(), 2); QCOMPARE(compositingChangedSpy.last().first().toBool(), false); QVERIFY(!KWindowSystem::compositingActive()); } QTEST_MAIN(KWindowEffectsTest) #include "kwindoweffectstest.moc" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0127833..0e64424 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,171 +1,171 @@ configure_file(config-kwindowsystem.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kwindowsystem.h ) ecm_create_qm_loader(kwindowsystem_QM_LOADER kwindowsystem5_qt) set(kwindowsystem_SRCS kkeyserver.cpp kstartupinfo.cpp kusertimestamp.cpp kwindoweffects.cpp kwindoweffects_dummy.cpp kwindowinfo.cpp kwindowsystem.cpp platforms/wayland/kwindowsystem.cpp pluginwrapper.cpp kwindowsystemplugininterface.cpp ${kwindowsystem_QM_LOADER} ) ecm_qt_declare_logging_category(kwindowsystem_SRCS HEADER kwindowsystem_debug.h IDENTIFIER LOG_KWINDOWSYSTEM CATEGORY_NAME org.kde.kwindowsystem DEFAULT_SEVERITY Warning) ecm_qt_declare_logging_category(kwindowsystem_SRCS HEADER kwindowsystem_xcb_debug.h IDENTIFIER LOG_KKEYSERVER_X11 CATEGORY_NAME org.kde.kwindowsystem.keyserver.x11 DEFAULT_SEVERITY Warning) if (KWINDOWSYSTEM_HAVE_X11) set(kwindowsystem_SRCS ${kwindowsystem_SRCS} platforms/xcb/kselectionowner.cpp platforms/xcb/kselectionwatcher.cpp platforms/xcb/kxerrorhandler.cpp platforms/xcb/kxutils.cpp ) endif() set(platformLinkLibraries) if (KWINDOWSYSTEM_HAVE_X11) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/platforms/xcb) if(NOT X11_Xrender_LIB) message(FATAL_ERROR "The XRender library could not be found. Please install the development package for it.") endif() if(NOT X11_Xfixes_LIB) message(FATAL_ERROR "The XFixes library could not be found. Please install the development package for it.") endif() set(platformLinkLibraries Qt5::X11Extras ${X11_LIBRARIES} ${X11_Xfixes_LIB} ${X11_Xrender_LIB} ${XCB_XCB_LIBRARY} ${XCB_KEYSYMS_LIBRARY}) set(kwindowsystem_SRCS ${kwindowsystem_SRCS} platforms/xcb/kkeyserver.cpp platforms/xcb/kxmessages.cpp platforms/xcb/netwm.cpp ) endif () if (APPLE) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/platforms/osx) set(kwindowsystem_SRCS ${kwindowsystem_SRCS} platforms/osx/kkeyserver.cpp # kwindowsystem_mac.cpp # FIXME: adjust kwindowinfo_mac to inherit from KWindowInfoPrivate # kwindowinfo_mac.cpp ) set(platformLinkLibraries "-framework CoreFoundation -framework Carbon") endif () if (WIN32) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/platforms/windows) set(kwindowsystem_SRCS ${kwindowsystem_SRCS} platforms/windows/kkeyserver.cpp # kwindowsystem_win.cpp # FIXME: adjust kwindowinfo_win to inherit from KWindowInfoPrivate # kwindowinfo_win.cpp ) set(platformLinkLibraries Qt5::WinExtras # QtWin::fromHICON(), QtWin::toHICON() ws2_32 # gethostname() ) endif () add_library(KF5WindowSystem ${kwindowsystem_SRCS}) add_library(KF5::WindowSystem ALIAS KF5WindowSystem) ecm_generate_export_header(KF5WindowSystem BASE_NAME KWindowSystem GROUP_BASE_NAME KF VERSION ${KF5_VERSION} DEPRECATED_BASE_VERSION 0 - DEPRECATION_VERSIONS 5.0 5.18 5.38 5.62 + DEPRECATION_VERSIONS 5.0 5.18 5.38 5.62 5.67 EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT} ) target_include_directories(KF5WindowSystem INTERFACE "$") target_link_libraries(KF5WindowSystem PUBLIC Qt5::Gui PRIVATE ${platformLinkLibraries} ) if(NOT KWINDOWSYSTEM_NO_WIDGETS) target_link_libraries(KF5WindowSystem PUBLIC Qt5::Widgets) endif() if(KWINDOWSYSTEM_HAVE_X11) # we install kkeyserver_x11.h which needs the X11 headers available # if we don't add the include path here code that includes kkeyserver.h will fail # to compile unless X11 is installed in /usr/include target_include_directories(KF5WindowSystem PUBLIC ${XCB_XCB_INCLUDE_DIR} ${X11_X11_INCLUDE_PATH}) endif() set_target_properties(KF5WindowSystem PROPERTIES VERSION ${KWINDOWSYSTEM_VERSION_STRING} SOVERSION ${KWINDOWSYSTEM_SOVERSION} EXPORT_NAME WindowSystem ) ecm_generate_headers(KWindowSystem_HEADERS HEADER_NAMES KKeyServer KStartupInfo KUserTimestamp KWindowEffects KWindowInfo KWindowSystem REQUIRED_HEADERS KWindowSystem_HEADERS ) install(TARGETS KF5WindowSystem EXPORT KF5WindowSystemTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES # FIXME: It seems odd to install this. ${CMAKE_CURRENT_BINARY_DIR}/config-kwindowsystem.h ${CMAKE_CURRENT_BINARY_DIR}/kwindowsystem_export.h ${KWindowSystem_HEADERS} netwm_def.h DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KWindowSystem COMPONENT Devel ) install( FILES kwindoweffects_p.h kwindowinfo_p.h kwindowsystem_p.h kwindowsystemplugininterface_p.h DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KWindowSystem/private COMPONENT Devel ) if(BUILD_QCH) ecm_add_qch( KF5WindowSystem_QCH NAME KWindowSystem BASE_NAME KF5WindowSystem VERSION ${KF5_VERSION} ORG_DOMAIN org.kde SOURCE_DIRS # using dir for now, to cover any platform dependant code # TODO: should only use public headers, to cover only public API ${CMAKE_CURRENT_SOURCE_DIR} MD_MAINPAGE "${CMAKE_SOURCE_DIR}/README.md" LINK_QCHS Qt5Gui_QCH INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR} BLANK_MACROS KWINDOWSYSTEM_EXPORT KWINDOWSYSTEM_DEPRECATED KWINDOWSYSTEM_DEPRECATED_EXPORT "KWINDOWSYSTEM_DEPRECATED_VERSION(x, y, t)" TAGFILE_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} QCH_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} COMPONENT Devel ) endif() add_subdirectory(platforms) include(ECMGeneratePriFile) ecm_generate_pri_file(BASE_NAME KWindowSystem LIB_NAME KF5WindowSystem DEPS "gui" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF5}/KWindowSystem) install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) diff --git a/src/kwindoweffects.cpp b/src/kwindoweffects.cpp index bea59a9..4958cf8 100644 --- a/src/kwindoweffects.cpp +++ b/src/kwindoweffects.cpp @@ -1,90 +1,92 @@ /* * Copyright 2014 Martin Gräßlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "kwindoweffects_p.h" #include "pluginwrapper_p.h" #include #if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 62) #include #endif KWindowEffectsPrivate::KWindowEffectsPrivate() { } KWindowEffectsPrivate::~KWindowEffectsPrivate() { } namespace KWindowEffects { bool isEffectAvailable(Effect effect) { return KWindowSystemPluginWrapper::self().effects()->isEffectAvailable(effect); } void enableBlurBehind(WId window, bool enable, const QRegion ®ion) { KWindowSystemPluginWrapper::self().effects()->enableBlurBehind(window, enable, region); } void enableBackgroundContrast(WId window, bool enable, qreal contrast, qreal intensity, qreal saturation, const QRegion ®ion) { KWindowSystemPluginWrapper::self().effects()->enableBackgroundContrast(window, enable, contrast, intensity, saturation, region); } void highlightWindows(WId controller, const QList< WId > &ids) { KWindowSystemPluginWrapper::self().effects()->highlightWindows(controller, ids); } +#if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 67) void markAsDashboard(WId window) { KWindowSystemPluginWrapper::self().effects()->markAsDashboard(window); } +#endif void presentWindows(WId controller, const QList< WId > &ids) { KWindowSystemPluginWrapper::self().effects()->presentWindows(controller, ids); } void presentWindows(WId controller, int desktop) { KWindowSystemPluginWrapper::self().effects()->presentWindows(controller, desktop); } void slideWindow(WId id, SlideFromLocation location, int offset) { KWindowSystemPluginWrapper::self().effects()->slideWindow(id, location, offset); } #if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 62) void slideWindow(QWidget *widget, SlideFromLocation location) { slideWindow(widget->effectiveWinId(), location, -1); } #endif QList< QSize > windowSizes(const QList< WId > &ids) { return KWindowSystemPluginWrapper::self().effects()->windowSizes(ids); } } diff --git a/src/kwindoweffects.h b/src/kwindoweffects.h index d292b10..d552f69 100644 --- a/src/kwindoweffects.h +++ b/src/kwindoweffects.h @@ -1,167 +1,173 @@ /* * Copyright 2009 Marco Martin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #ifndef KWINDOWEFFECTS_H #define KWINDOWEFFECTS_H #include "kwindowsystem_export.h" #include // for WId, etc. #include #include /** * Namespace for common standardized window effects */ namespace KWindowEffects { enum Effect { Slide = 1, PresentWindows = 3, PresentWindowsGroup = 4, HighlightWindows = 5, BlurBehind = 7, +#if KWINDOWSYSTEM_ENABLE_DEPRECATED_SINCE(5, 67) Dashboard = 8, +#endif BackgroundContrast = 9 }; enum SlideFromLocation { NoEdge = 0, TopEdge, RightEdge, BottomEdge, LeftEdge }; /** * @return if an atom property is available * * @param effect the effect we want to check */ KWINDOWSYSTEM_EXPORT bool isEffectAvailable(Effect effect); /** * Mark a window as sliding from screen edge * * @param id of the window on which we want to apply the effect * @param location edge of the screen from which we want the sliding effect. * Desktop and Floating won't have effect. * @param offset distance in pixels from the screen edge defined by location */ KWINDOWSYSTEM_EXPORT void slideWindow(WId id, SlideFromLocation location, int offset = -1); #if KWINDOWSYSTEM_ENABLE_DEPRECATED_SINCE(5, 62) /** * Mark a window as sliding from screen edge * This is an overloaded member function provided for convenience * * @param widget QWidget corresponding to the top level window we want to animate * @param location edge of the screen from which we want the sliding effect. * Desktop and Floating won't have effect. * @deprecated since 5.62, use slideWindow(widget->effectiveWinId(), location); */ KWINDOWSYSTEM_DEPRECATED_VERSION(5, 62, "Use KWindowEffects::slideWindow(WId, SlideFromLocation, int)") KWINDOWSYSTEM_EXPORT void slideWindow(QWidget *widget, SlideFromLocation location); #endif /** * @return dimension of all the windows passed as parameter * * @param ids all the windows we want the size */ KWINDOWSYSTEM_EXPORT QList windowSizes(const QList &ids); /** * Activate the Present Windows effect for the given groups of windows. * * @param controller The window which is the controller of this effect. The property * will be set on this window. It will be removed by the effect * @param ids all the windows which should be presented. */ KWINDOWSYSTEM_EXPORT void presentWindows(WId controller, const QList &ids); /** * Activate the Present Windows effect for the windows of the given desktop. * * @param controller The window which is the controller of this effect. The property * will be set on this window. It will be removed by the effect * @param desktop The desktop whose windows should be presented. -1 for all desktops */ KWINDOWSYSTEM_EXPORT void presentWindows(WId controller, int desktop = NET::OnAllDesktops); /** * Highlight the selected windows, making all the others translucent * * @param controller The window which is the controller of this effect. The property * will be set on this window. It will be removed by the effect * @param ids all the windows which should be highlighted. */ KWINDOWSYSTEM_EXPORT void highlightWindows(WId controller, const QList &ids); /** * Instructs the window manager to blur the background * in the specified region behind the given window. * The given region will overwrite any previous blur-behind region. * Passing a null region will enable the blur effect for the whole window. * The region is relative to the top-left corner of the client area. * * If @a enable is @c false, blur will be disabled for the whole window * (@a region is ignored). * * Note that you will usually want to set the region to the shape of the window, * excluding any shadow or halo. * * @param window The window for which to enable the blur effect * @param enable Enable the effect if @c true, disable it if @c false * @param region The region within the window where the background will be blurred, specified in logical pixels */ KWINDOWSYSTEM_EXPORT void enableBlurBehind(WId window, bool enable = true, const QRegion ®ion = QRegion()); /** * Instructs the window manager to modify the color of the background * in the specified region behind the given window, * in order to improve the contrast and readability of any text * in the translucent window. * The given region will overwrite any previous backgroundcontrast region. * Passing a null region will enable the blur effect for the whole window. * The region is relative to the top-left corner of the client area. * * If @a enable is @c false, blur will be disabled for the whole window * (@a region is ignored). * * Note that you will usually want to set the region to the shape of the window, * excluding any shadow or halo. * * @param window The window for which to enable the background contrast effect * @param enable Enable the effect if @c true, disable it if @c false * @param brightness How to modify the area brightness: from 0 (make it black) to 2 (make it white), 1 leaves it unchanged * @param region The region within the window where the background will be modified, specified in logical pixels */ KWINDOWSYSTEM_EXPORT void enableBackgroundContrast(WId window, bool enable = true, qreal contrast = 1, qreal intensity = 1, qreal saturation = 1, const QRegion ®ion = QRegion()); +#if KWINDOWSYSTEM_ENABLE_DEPRECATED_SINCE(5, 67) /** * Instructs the window manager to handle the given window as dashboard window as * Dashboard windows should be handled diffrently and may have special effects * applied to them. * * @param window The window for which to enable the blur effect + * @deprecated since 5.67, support for dashboard windows was removed */ +KWINDOWSYSTEM_DEPRECATED_VERSION(5, 67, "Support for dashboard windows was removed") KWINDOWSYSTEM_EXPORT void markAsDashboard(WId window); +#endif } #endif diff --git a/src/kwindoweffects_dummy.cpp b/src/kwindoweffects_dummy.cpp index 4726486..b454637 100644 --- a/src/kwindoweffects_dummy.cpp +++ b/src/kwindoweffects_dummy.cpp @@ -1,90 +1,92 @@ /* * Copyright 2009 Marco Martin * Copyright 2014 Martin Gräßlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "kwindoweffects_dummy_p.h" KWindowEffectsPrivateDummy::KWindowEffectsPrivateDummy() { } KWindowEffectsPrivateDummy::~KWindowEffectsPrivateDummy() { } bool KWindowEffectsPrivateDummy::isEffectAvailable(KWindowEffects::Effect effect) { Q_UNUSED(effect) return false; } void KWindowEffectsPrivateDummy::slideWindow(WId id, KWindowEffects::SlideFromLocation location, int offset) { Q_UNUSED(id) Q_UNUSED(location) Q_UNUSED(offset) } QList KWindowEffectsPrivateDummy::windowSizes(const QList &ids) { QList windowSizes; windowSizes.reserve(ids.size()); for (int i = 0; i < ids.size(); ++i) { windowSizes.append(QSize()); } return windowSizes; } void KWindowEffectsPrivateDummy::presentWindows(WId controller, const QList &ids) { Q_UNUSED(controller) Q_UNUSED(ids) } void KWindowEffectsPrivateDummy::presentWindows(WId controller, int desktop) { Q_UNUSED(controller) Q_UNUSED(desktop) } void KWindowEffectsPrivateDummy::highlightWindows(WId controller, const QList &ids) { Q_UNUSED(controller) Q_UNUSED(ids) } void KWindowEffectsPrivateDummy::enableBlurBehind(WId window, bool enable, const QRegion ®ion) { Q_UNUSED(window) Q_UNUSED(enable) Q_UNUSED(region) } void KWindowEffectsPrivateDummy::enableBackgroundContrast(WId window, bool enable, qreal contrast, qreal intensity, qreal saturation, const QRegion ®ion) { Q_UNUSED(window) Q_UNUSED(enable) Q_UNUSED(contrast) Q_UNUSED(intensity) Q_UNUSED(saturation) Q_UNUSED(region) } +#if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 67) void KWindowEffectsPrivateDummy::markAsDashboard(WId window) { Q_UNUSED(window) } +#endif diff --git a/src/kwindoweffects_dummy_p.h b/src/kwindoweffects_dummy_p.h index 9dcac5e..e2a31e7 100644 --- a/src/kwindoweffects_dummy_p.h +++ b/src/kwindoweffects_dummy_p.h @@ -1,40 +1,42 @@ /* * Copyright 2014 Martin Gräßlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #ifndef KWINDOWEFFECTS_DUMMY_P_H #define KWINDOWEFFECTS_DUMMY_P_H #include "kwindoweffects_p.h" class KWindowEffectsPrivateDummy : public KWindowEffectsPrivate { public: KWindowEffectsPrivateDummy(); ~KWindowEffectsPrivateDummy() override; bool isEffectAvailable(KWindowEffects::Effect effect) override; void slideWindow(WId id, KWindowEffects::SlideFromLocation location, int offset) override; QList< QSize > windowSizes(const QList &ids) override; void presentWindows(WId controller, const QList &ids) override; void presentWindows(WId controller, int desktop = NET::OnAllDesktops) override; void highlightWindows(WId controller, const QList &ids) override; void enableBlurBehind(WId window, bool enable = true, const QRegion& region = QRegion()) override; void enableBackgroundContrast(WId window, bool enable = true, qreal contrast = 1, qreal intensity = 1, qreal saturation = 1, const QRegion ®ion = QRegion()) override; +#if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 67) void markAsDashboard(WId window) override; +#endif }; #endif diff --git a/src/kwindoweffects_p.h b/src/kwindoweffects_p.h index f781c8b..a8860bb 100644 --- a/src/kwindoweffects_p.h +++ b/src/kwindoweffects_p.h @@ -1,41 +1,43 @@ /* * Copyright 2014 Martin Gräßlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #ifndef KWINDOWEFFECTS_P_H #define KWINDOWEFFECTS_P_H #include "kwindoweffects.h" class KWINDOWSYSTEM_EXPORT KWindowEffectsPrivate { public: virtual ~KWindowEffectsPrivate(); virtual bool isEffectAvailable(KWindowEffects::Effect effect) = 0; virtual void slideWindow(WId id, KWindowEffects::SlideFromLocation location, int offset) = 0; virtual QList windowSizes(const QList &ids) = 0; virtual void presentWindows(WId controller, const QList &ids) = 0; virtual void presentWindows(WId controller, int desktop = NET::OnAllDesktops) = 0; virtual void highlightWindows(WId controller, const QList &ids) = 0; virtual void enableBlurBehind(WId window, bool enable = true, const QRegion ®ion = QRegion()) = 0; virtual void enableBackgroundContrast(WId window, bool enable = true, qreal contrast = 1, qreal intensity = 1, qreal saturation = 1, const QRegion ®ion = QRegion()) = 0; +#if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 67) virtual void markAsDashboard(WId window) = 0; +#endif protected: KWindowEffectsPrivate(); }; #endif diff --git a/src/platforms/xcb/kwindoweffects.cpp b/src/platforms/xcb/kwindoweffects.cpp index f6bc7b0..0732efa 100644 --- a/src/platforms/xcb/kwindoweffects.cpp +++ b/src/platforms/xcb/kwindoweffects.cpp @@ -1,343 +1,346 @@ /* * Copyright 2009 Marco Martin * Copyright 2014 Martin Gräßlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "kwindoweffects_x11.h" #include #include #include "kwindowsystem.h" #include #include #include #include -static const char DASHBOARD_WIN_CLASS[] = "dashboard\0dashboard"; using namespace KWindowEffects; KWindowEffectsPrivateX11::KWindowEffectsPrivateX11() { } KWindowEffectsPrivateX11::~KWindowEffectsPrivateX11() { } bool KWindowEffectsPrivateX11::isEffectAvailable(Effect effect) { if (!KWindowSystem::self()->compositingActive()) { return false; } QByteArray effectName; switch (effect) { case Slide: effectName = QByteArrayLiteral("_KDE_SLIDE"); break; case PresentWindows: effectName = QByteArrayLiteral("_KDE_PRESENT_WINDOWS_DESKTOP"); break; case PresentWindowsGroup: effectName = QByteArrayLiteral("_KDE_PRESENT_WINDOWS_GROUP"); break; case HighlightWindows: effectName = QByteArrayLiteral("_KDE_WINDOW_HIGHLIGHT"); break; case BlurBehind: effectName = QByteArrayLiteral("_KDE_NET_WM_BLUR_BEHIND_REGION"); break; +#if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 67) case Dashboard: // TODO: Better namespacing for atoms effectName = QByteArrayLiteral("_WM_EFFECT_KDE_DASHBOARD"); break; +#endif case BackgroundContrast: effectName = QByteArrayLiteral("_KDE_NET_WM_BACKGROUND_CONTRAST_REGION"); break; default: return false; } // hackish way to find out if KWin has the effect enabled, // TODO provide proper support xcb_connection_t *c = QX11Info::connection(); xcb_list_properties_cookie_t propsCookie = xcb_list_properties_unchecked(c, QX11Info::appRootWindow()); xcb_intern_atom_cookie_t atomCookie = xcb_intern_atom_unchecked(c, false, effectName.length(), effectName.constData()); QScopedPointer props(xcb_list_properties_reply(c, propsCookie, nullptr)); QScopedPointer atom(xcb_intern_atom_reply(c, atomCookie, nullptr)); if (!atom || !props) { return false; } xcb_atom_t *atoms = xcb_list_properties_atoms(props.data()); for (int i = 0; i < props->atoms_len; ++i) { if (atoms[i] == atom->atom) { return true; } } return false; } void KWindowEffectsPrivateX11::slideWindow(WId id, SlideFromLocation location, int offset) { xcb_connection_t *c = QX11Info::connection(); if (!c) { return; } const QByteArray effectName = QByteArrayLiteral("_KDE_SLIDE"); xcb_intern_atom_cookie_t atomCookie = xcb_intern_atom_unchecked(c, false, effectName.length(), effectName.constData()); const int size = 2; int32_t data[size]; data[0] = offset; switch (location) { case LeftEdge: data[1] = 0; break; case TopEdge: data[1] = 1; break; case RightEdge: data[1] = 2; break; case BottomEdge: data[1] = 3; default: break; } QScopedPointer atom(xcb_intern_atom_reply(c, atomCookie, nullptr)); if (!atom) { return; } if (location == NoEdge) { xcb_delete_property(c, id, atom->atom); } else { xcb_change_property(c, XCB_PROP_MODE_REPLACE, id, atom->atom, atom->atom, 32, size, data); } } QList KWindowEffectsPrivateX11::windowSizes(const QList &ids) { QList windowSizes; for (WId id : ids) { if (id > 0) { KWindowInfo info(id, NET::WMGeometry | NET::WMFrameExtents); windowSizes.append(info.frameGeometry().size()); } else { windowSizes.append(QSize()); } } return windowSizes; } void KWindowEffectsPrivateX11::presentWindows(WId controller, const QList &ids) { xcb_connection_t *c = QX11Info::connection(); if (!c) { return; } const int numWindows = ids.count(); QVarLengthArray data(numWindows); int actualCount = 0; for (int i = 0; i < numWindows; ++i) { data[i] = ids.at(i); ++actualCount; } if (actualCount != numWindows) { data.resize(actualCount); } if (data.isEmpty()) { return; } const QByteArray effectName = QByteArrayLiteral("_KDE_PRESENT_WINDOWS_GROUP"); xcb_intern_atom_cookie_t atomCookie = xcb_intern_atom_unchecked(c, false, effectName.length(), effectName.constData()); QScopedPointer atom(xcb_intern_atom_reply(c, atomCookie, nullptr)); if (!atom) { return; } xcb_change_property(c, XCB_PROP_MODE_REPLACE, controller, atom->atom, atom->atom, 32, data.size(), data.constData()); } void KWindowEffectsPrivateX11::presentWindows(WId controller, int desktop) { xcb_connection_t *c = QX11Info::connection(); if (!c) { return; } const QByteArray effectName = QByteArrayLiteral("_KDE_PRESENT_WINDOWS_DESKTOP"); xcb_intern_atom_cookie_t atomCookie = xcb_intern_atom_unchecked(c, false, effectName.length(), effectName.constData()); QScopedPointer atom(xcb_intern_atom_reply(c, atomCookie, nullptr)); if (!atom) { return; } int32_t data = desktop; xcb_change_property(c, XCB_PROP_MODE_REPLACE, controller, atom->atom, atom->atom, 32, 1, &data); } void KWindowEffectsPrivateX11::highlightWindows(WId controller, const QList &ids) { xcb_connection_t *c = QX11Info::connection(); if (!c) { return; } const QByteArray effectName = QByteArrayLiteral("_KDE_WINDOW_HIGHLIGHT"); xcb_intern_atom_cookie_t atomCookie = xcb_intern_atom_unchecked(c, false, effectName.length(), effectName.constData()); QScopedPointer atom(xcb_intern_atom_reply(c, atomCookie, nullptr)); if (!atom) { return; } const int numWindows = ids.count(); if (numWindows == 0) { xcb_delete_property(c, controller, atom->atom); return; } QVarLengthArray data(numWindows); int actualCount = 0; for (int i = 0; i < numWindows; ++i) { data[i] = ids.at(i); ++actualCount; } if (actualCount != numWindows) { data.resize(actualCount); } if (data.isEmpty()) { return; } xcb_change_property(c, XCB_PROP_MODE_REPLACE, controller, atom->atom, atom->atom, 32, data.size(), data.constData()); } void KWindowEffectsPrivateX11::enableBlurBehind(WId window, bool enable, const QRegion ®ion) { xcb_connection_t *c = QX11Info::connection(); if (!c) { return; } const QByteArray effectName = QByteArrayLiteral("_KDE_NET_WM_BLUR_BEHIND_REGION"); xcb_intern_atom_cookie_t atomCookie = xcb_intern_atom_unchecked(c, false, effectName.length(), effectName.constData()); QScopedPointer atom(xcb_intern_atom_reply(c, atomCookie, nullptr)); if (!atom) { return; } if (enable) { QVector data; data.reserve(region.rectCount() * 4); for (const QRect& r : region) { // kwin on X uses device pixels, convert from logical auto dpr = qApp->devicePixelRatio(); data << r.x() * dpr << r.y() * dpr << r.width() * dpr << r.height() * dpr; } xcb_change_property(c, XCB_PROP_MODE_REPLACE, window, atom->atom, XCB_ATOM_CARDINAL, 32, data.size(), data.constData()); } else { xcb_delete_property(c, window, atom->atom); } } void KWindowEffectsPrivateX11::enableBackgroundContrast(WId window, bool enable, qreal contrast, qreal intensity, qreal saturation, const QRegion ®ion) { xcb_connection_t *c = QX11Info::connection(); const QByteArray effectName = QByteArrayLiteral("_KDE_NET_WM_BACKGROUND_CONTRAST_REGION"); xcb_intern_atom_cookie_t atomCookie = xcb_intern_atom_unchecked(c, false, effectName.length(), effectName.constData()); QScopedPointer atom(xcb_intern_atom_reply(c, atomCookie, nullptr)); if (!atom) { return; } if (enable) { QVector data; data.reserve(region.rectCount() * 4 + 16); for (const QRect& r : region) { auto dpr = qApp->devicePixelRatio(); data << r.x() * dpr << r.y() * dpr << r.width() * dpr << r.height() * dpr; } QMatrix4x4 satMatrix; //saturation QMatrix4x4 intMatrix; //intensity QMatrix4x4 contMatrix; //contrast //Saturation matrix if (!qFuzzyCompare(saturation, 1.0)) { const qreal rval = (1.0 - saturation) * .2126; const qreal gval = (1.0 - saturation) * .7152; const qreal bval = (1.0 - saturation) * .0722; satMatrix = QMatrix4x4(rval + saturation, rval, rval, 0.0, gval, gval + saturation, gval, 0.0, bval, bval, bval + saturation, 0.0, 0, 0, 0, 1.0); } //IntensityMatrix if (!qFuzzyCompare(intensity, 1.0)) { intMatrix.scale(intensity, intensity, intensity); } //Contrast Matrix if (!qFuzzyCompare(contrast, 1.0)) { const float transl = (1.0 - contrast) / 2.0; contMatrix = QMatrix4x4(contrast, 0, 0, 0.0, 0, contrast, 0, 0.0, 0, 0, contrast, 0.0, transl, transl, transl, 1.0); } QMatrix4x4 colorMatrix = contMatrix * satMatrix * intMatrix; colorMatrix = colorMatrix.transposed(); uint32_t *rawData = reinterpret_cast(colorMatrix.data()); for (int i = 0; i < 16; ++i) { data << rawData[i]; } xcb_change_property(c, XCB_PROP_MODE_REPLACE, window, atom->atom, atom->atom, 32, data.size(), data.constData()); } else { xcb_delete_property(c, window, atom->atom); } } +#if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 67) void KWindowEffectsPrivateX11::markAsDashboard(WId window) { + static const char DASHBOARD_WIN_CLASS[] = "dashboard\0dashboard"; xcb_connection_t *c = QX11Info::connection(); if (!c) { return; } xcb_change_property(c, XCB_PROP_MODE_REPLACE, window, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 8, 19, DASHBOARD_WIN_CLASS); } - +#endif diff --git a/src/platforms/xcb/kwindoweffects_x11.h b/src/platforms/xcb/kwindoweffects_x11.h index ac9737d..966c921 100644 --- a/src/platforms/xcb/kwindoweffects_x11.h +++ b/src/platforms/xcb/kwindoweffects_x11.h @@ -1,40 +1,42 @@ /* * Copyright 2014 Martin Gräßlin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #ifndef KWINDOWEFFECTS_X11_H #define KWINDOWEFFECTS_X11_H #include "kwindoweffects_p.h" class KWindowEffectsPrivateX11 : public KWindowEffectsPrivate { public: KWindowEffectsPrivateX11(); ~KWindowEffectsPrivateX11() override; bool isEffectAvailable(KWindowEffects::Effect effect) override; void slideWindow(WId id, KWindowEffects::SlideFromLocation location, int offset) override; QList< QSize > windowSizes(const QList &ids) override; void presentWindows(WId controller, const QList &ids) override; void presentWindows(WId controller, int desktop = NET::OnAllDesktops) override; void highlightWindows(WId controller, const QList &ids) override; void enableBlurBehind(WId window, bool enable = true, const QRegion& region = QRegion()) override; void enableBackgroundContrast(WId window, bool enable = true, qreal contrast = 1, qreal intensity = 1, qreal saturation = 1, const QRegion ®ion = QRegion()) override; +#if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 67) void markAsDashboard(WId window) override; +#endif }; #endif