Make it possible to build KWin without libxcb

Now that we have Wayland around, there's a whole branch of dependencies
that shouldn't be necessary anymore.
This allows to build KWin without all of it, allowing us to have a much
more compact alignment for cases where all the legacy software isn't
necessary anymore.

Bundle KWindowSystem X11-specific headers into it too, since it's part
of the same process.

Signed-off-by: Victoria Fischer <victoria.fischer@mbition.io>
This commit is contained in:
Aleix Pol Gonzalez 2023-12-15 17:58:46 +01:00 committed by Aleix Pol Gonzalez
parent 94121c2a42
commit bf1ce85474
94 changed files with 1484 additions and 740 deletions

View file

@ -11,4 +11,4 @@ suse_tumbleweed_qt66_reduced_featureset:
extends: suse_tumbleweed_qt66
script:
- git config --global --add safe.directory $CI_PROJECT_DIR
- python3 -u ci-utilities/run-ci-build.py --project $CI_PROJECT_NAME --branch $CI_COMMIT_REF_NAME --platform Linux --extra-cmake-args="-DKWIN_BUILD_KCMS=OFF -DKWIN_BUILD_SCREENLOCKER=OFF -DKWIN_BUILD_TABBOX=OFF -DKWIN_BUILD_ACTIVITIES=OFF -DKWIN_BUILD_RUNNERS=OFF -DKWIN_BUILD_NOTIFICATIONS=OFF -DKWIN_BUILD_GLOBALSHORTCUTS=OFF" --skip-publishing
- python3 -u ci-utilities/run-ci-build.py --project $CI_PROJECT_NAME --branch $CI_COMMIT_REF_NAME --platform Linux --extra-cmake-args="-DKWIN_BUILD_KCMS=OFF -DKWIN_BUILD_SCREENLOCKER=OFF -DKWIN_BUILD_TABBOX=OFF -DKWIN_BUILD_ACTIVITIES=OFF -DKWIN_BUILD_RUNNERS=OFF -DKWIN_BUILD_NOTIFICATIONS=OFF -DKWIN_BUILD_GLOBALSHORTCUTS=OFF -DKWIN_BUILD_X11=OFF" --skip-publishing

View file

@ -47,6 +47,7 @@ option(KWIN_BUILD_KCMS "Enable building of KWin configuration modules." ON)
option(KWIN_BUILD_NOTIFICATIONS "Enable building of KWin with knotifications support" ON)
option(KWIN_BUILD_SCREENLOCKER "Enable building of KWin lockscreen functionality" ON)
option(KWIN_BUILD_TABBOX "Enable building of KWin Tabbox functionality" ON)
option(KWIN_BUILD_X11 "Enable building kwin_x11 and Xwayland support" ON)
find_package(Qt6 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
Concurrent
@ -232,8 +233,58 @@ else()
set(HAVE_XKBCOMMON_NO_SECURE_GETENV 0)
endif()
pkg_check_modules(XKBX11 IMPORTED_TARGET xkbcommon-x11 REQUIRED)
add_feature_info(XKBX11 XKBX11_FOUND "Required for handling keyboard events in X11 backend")
if (KWIN_BUILD_X11)
pkg_check_modules(XKBX11 IMPORTED_TARGET xkbcommon-x11 REQUIRED)
add_feature_info(XKBX11 XKBX11_FOUND "Required for handling keyboard events in X11 backend")
# All the required XCB components
find_package(XCB 1.10 REQUIRED COMPONENTS
COMPOSITE
CURSOR
DAMAGE
DRI3
GLX
ICCCM
IMAGE
KEYSYMS
PRESENT
RANDR
RENDER
SHAPE
SHM
SYNC
XCB
XFIXES
XKB
XINERAMA
)
set_package_properties(XCB PROPERTIES TYPE REQUIRED)
find_package(X11_XCB)
set_package_properties(X11_XCB PROPERTIES
PURPOSE "Required for building X11 windowed backend of kwin_wayland"
TYPE OPTIONAL
)
find_package(Xwayland)
set_package_properties(Xwayland PROPERTIES
URL "https://x.org"
DESCRIPTION "Xwayland X server"
TYPE RUNTIME
PURPOSE "Needed for running kwin_wayland"
)
set(HAVE_XWAYLAND_LISTENFD ${Xwayland_HAVE_LISTENFD})
set(HAVE_GLX ${epoxy_HAS_GLX})
get_target_property(QT_DISABLED_FEATURES Qt6::Gui QT_DISABLED_PUBLIC_FEATURES)
if("xcb_glx_plugin" IN_LIST QT_DISABLED_FEATURES)
message(STATUS "Disable GLX because Qt6::Gui was built without xcb_glx_plugin")
set(HAVE_GLX false)
endif()
# for kwin internal things
set(HAVE_X11_XCB ${X11_XCB_FOUND})
endif()
find_package(Libinput 1.19)
set_package_properties(Libinput PROPERTIES TYPE REQUIRED PURPOSE "Required for input handling on Wayland.")
@ -282,35 +333,6 @@ set_package_properties(lcms2 PROPERTIES
PURPOSE "Required for the color management system"
)
# All the required XCB components
find_package(XCB 1.10 REQUIRED COMPONENTS
COMPOSITE
CURSOR
DAMAGE
DRI3
GLX
ICCCM
IMAGE
KEYSYMS
PRESENT
RANDR
RENDER
SHAPE
SHM
SYNC
XCB
XFIXES
XKB
XINERAMA
)
set_package_properties(XCB PROPERTIES TYPE REQUIRED)
find_package(X11_XCB)
set_package_properties(X11_XCB PROPERTIES
PURPOSE "Required for building X11 windowed backend of kwin_wayland"
TYPE OPTIONAL
)
find_package(Freetype)
set_package_properties(Freetype PROPERTIES
DESCRIPTION "A font rendering engine"
@ -324,15 +346,6 @@ set_package_properties(Fontconfig PROPERTIES
PURPOSE "Needed for KWin's QPA plugin."
)
find_package(Xwayland)
set_package_properties(Xwayland PROPERTIES
URL "https://x.org"
DESCRIPTION "Xwayland X server"
TYPE RUNTIME
PURPOSE "Needed for running kwin_wayland"
)
set(HAVE_XWAYLAND_LISTENFD ${Xwayland_HAVE_LISTENFD})
find_package(Libcap)
set_package_properties(Libcap PROPERTIES
TYPE OPTIONAL
@ -382,16 +395,6 @@ ecm_find_qmlmodule(org.kde.plasma.components 2.0)
cmake_dependent_option(KWIN_BUILD_ACTIVITIES "Enable building of KWin with kactivities support" ON "PlasmaActivities_FOUND" OFF)
option(KWIN_BUILD_RUNNERS "Enable building of KWin with krunner support" ON)
set(HAVE_GLX ${epoxy_HAS_GLX})
get_target_property(QT_DISABLED_FEATURES Qt6::Gui QT_DISABLED_PUBLIC_FEATURES)
if("xcb_glx_plugin" IN_LIST QT_DISABLED_FEATURES)
message(STATUS "Disable GLX because Qt6::Gui was built without xcb_glx_plugin")
set(HAVE_GLX false)
endif()
# for kwin internal things
set(HAVE_X11_XCB ${X11_XCB_FOUND})
check_symbol_exists(SCHED_RESET_ON_FORK "sched.h" HAVE_SCHED_RESET_ON_FORK)
add_feature_info("SCHED_RESET_ON_FORK"
HAVE_SCHED_RESET_ON_FORK

View file

@ -45,82 +45,97 @@ ecm_mark_as_test(testVirtualDesktops)
########################################################
# Test ClientMachine
########################################################
set(testClientMachine_SRCS
../src/client_machine.cpp
test_client_machine.cpp
xcb_scaling_mock.cpp
)
add_executable(testClientMachine ${testClientMachine_SRCS})
set_target_properties(testClientMachine PROPERTIES COMPILE_DEFINITIONS "NO_NONE_WINDOW")
if(KWIN_BUILD_X11)
set(testClientMachine_SRCS
../src/client_machine.cpp
test_client_machine.cpp
xcb_scaling_mock.cpp
)
add_executable(testClientMachine ${testClientMachine_SRCS})
set_target_properties(testClientMachine PROPERTIES COMPILE_DEFINITIONS "NO_NONE_WINDOW")
target_link_libraries(testClientMachine
Qt::Concurrent
Qt::GuiPrivate
Qt::Test
Qt::Widgets
target_link_libraries(testClientMachine
Qt::Concurrent
Qt::GuiPrivate
Qt::Test
Qt::Widgets
KF6::ConfigCore
KF6::WindowSystem
KF6::ConfigCore
KF6::WindowSystem
XCB::XCB
XCB::XFIXES
XCB::XCB
XCB::XFIXES
${X11_X11_LIB} # to make jenkins happy
)
add_test(NAME kwin-testClientMachine COMMAND testClientMachine)
ecm_mark_as_test(testClientMachine)
${X11_X11_LIB} # to make jenkins happy
)
add_test(NAME kwin-testClientMachine COMMAND testClientMachine)
ecm_mark_as_test(testClientMachine)
########################################################
# Test XcbWrapper
########################################################
add_executable(testXcbWrapper test_xcb_wrapper.cpp xcb_scaling_mock.cpp)
########################################################
# Test XcbWrapper
########################################################
add_executable(testXcbWrapper test_xcb_wrapper.cpp xcb_scaling_mock.cpp)
target_link_libraries(testXcbWrapper
Qt::GuiPrivate
Qt::Test
Qt::Widgets
target_link_libraries(testXcbWrapper
Qt::GuiPrivate
Qt::Test
Qt::Widgets
KF6::ConfigCore
KF6::WindowSystem
KF6::ConfigCore
KF6::WindowSystem
XCB::XCB
)
add_test(NAME kwin-testXcbWrapper COMMAND testXcbWrapper)
ecm_mark_as_test(testXcbWrapper)
XCB::XCB
)
add_test(NAME kwin-testXcbWrapper COMMAND testXcbWrapper)
ecm_mark_as_test(testXcbWrapper)
add_executable(testXcbSizeHints test_xcb_size_hints.cpp xcb_scaling_mock.cpp)
set_target_properties(testXcbSizeHints PROPERTIES COMPILE_DEFINITIONS "NO_NONE_WINDOW")
target_link_libraries(testXcbSizeHints
Qt::GuiPrivate
Qt::Test
Qt::Widgets
add_executable(testXcbSizeHints test_xcb_size_hints.cpp xcb_scaling_mock.cpp)
set_target_properties(testXcbSizeHints PROPERTIES COMPILE_DEFINITIONS "NO_NONE_WINDOW")
target_link_libraries(testXcbSizeHints
Qt::GuiPrivate
Qt::Test
Qt::Widgets
KF6::ConfigCore
KF6::WindowSystem
KF6::ConfigCore
KF6::WindowSystem
XCB::ICCCM
XCB::XCB
)
add_test(NAME kwin-testXcbSizeHints COMMAND testXcbSizeHints)
ecm_mark_as_test(testXcbSizeHints)
XCB::ICCCM
XCB::XCB
)
add_test(NAME kwin-testXcbSizeHints COMMAND testXcbSizeHints)
ecm_mark_as_test(testXcbSizeHints)
########################################################
# Test XcbWindow
########################################################
add_executable(testXcbWindow test_xcb_window.cpp xcb_scaling_mock.cpp)
########################################################
# Test XcbWindow
########################################################
add_executable(testXcbWindow test_xcb_window.cpp xcb_scaling_mock.cpp)
target_link_libraries(testXcbWindow
Qt::GuiPrivate
Qt::Test
Qt::Widgets
target_link_libraries(testXcbWindow
Qt::GuiPrivate
Qt::Test
Qt::Widgets
KF6::ConfigCore
KF6::WindowSystem
KF6::ConfigCore
KF6::WindowSystem
XCB::XCB
)
add_test(NAME kwin-testXcbWindow COMMAND testXcbWindow)
ecm_mark_as_test(testXcbWindow)
XCB::XCB
)
add_test(NAME kwin-testXcbWindow COMMAND testXcbWindow)
ecm_mark_as_test(testXcbWindow)
########################################################
# Test X11 TimestampUpdate
########################################################
add_executable(testX11TimestampUpdate test_x11_timestamp_update.cpp)
target_link_libraries(testX11TimestampUpdate
KF6::CoreAddons
Qt::Test
Qt::GuiPrivate
kwin
)
add_test(NAME kwin-testX11TimestampUpdate COMMAND testX11TimestampUpdate)
ecm_mark_as_test(testX11TimestampUpdate)
endif()
########################################################
# Test OnScreenNotification
@ -161,19 +176,6 @@ target_link_libraries(testGestures
add_test(NAME kwin-testGestures COMMAND testGestures)
ecm_mark_as_test(testGestures)
########################################################
# Test X11 TimestampUpdate
########################################################
add_executable(testX11TimestampUpdate test_x11_timestamp_update.cpp)
target_link_libraries(testX11TimestampUpdate
KF6::CoreAddons
Qt::Test
Qt::GuiPrivate
kwin
)
add_test(NAME kwin-testX11TimestampUpdate COMMAND testX11TimestampUpdate)
ecm_mark_as_test(testX11TimestampUpdate)
set(testOpenGLContextAttributeBuilder_SRCS
../src/opengl/abstract_opengl_context_attribute_builder.cpp
../src/opengl/egl_context_attribute_builder.cpp

View file

@ -39,7 +39,6 @@ target_link_libraries(LibDrmTest
KF6::WindowSystem
KF6::CoreAddons
KF6::I18n
XCB::XCB
PkgConfig::Libxcvt
gbm::gbm
Libdrm::Libdrm

View file

@ -14,7 +14,10 @@ kwineffects_unit_tests(
timelinetest
)
add_executable(kwinglplatformtest kwinglplatformtest.cpp mock_gl.cpp ../../src/opengl/glplatform.cpp ../../src/opengl/openglcontext.cpp ../../src/utils/version.cpp)
add_test(NAME kwineffects-kwinglplatformtest COMMAND kwinglplatformtest)
target_link_libraries(kwinglplatformtest Qt::Test Qt::Gui KF6::ConfigCore XCB::XCB)
ecm_mark_as_test(kwinglplatformtest)
if (KWIN_BUILD_X11 AND ARGS_LIBS MATCHES .*XCB.*)
add_executable(kwinglplatformtest kwinglplatformtest.cpp mock_gl.cpp ../../src/opengl/glplatform.cpp ../../src/opengl/openglcontext.cpp ../../src/utils/version.cpp)
add_test(NAME kwineffects-kwinglplatformtest COMMAND kwinglplatformtest)
target_link_libraries(kwinglplatformtest Qt::Test Qt::Gui KF6::ConfigCore XCB::XCB)
ecm_mark_as_test(kwinglplatformtest)
endif()

View file

@ -33,20 +33,21 @@ target_sources(KWinIntegrationTestFramework PRIVATE
target_link_libraries(KWinIntegrationTestFramework
PUBLIC
Qt::Test
Qt::Concurrent
Plasma::KWaylandClient
Wayland::Client
Libdrm::Libdrm
kwin
PRIVATE
# Own libraries
KWinXwaylandServerModule
# Static plugins
KWinQpaPlugin
KF6WindowSystemKWinPlugin
KF6IdleTimeKWinPlugin
)
if(KWIN_BUILD_X11)
target_link_libraries(KWinIntegrationTestFramework PRIVATE KWinXwaylandServerModule)
endif()
if(TARGET KF6GlobalAccelKWinPlugin)
target_link_libraries(KWinIntegrationTestFramework PUBLIC KF6GlobalAccelKWinPlugin)
endif()
@ -60,6 +61,9 @@ function(integrationTest)
set(oneValueArgs NAME)
set(multiValueArgs SRCS LIBS)
cmake_parse_arguments(ARGS "${optionArgs}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if (NOT KWIN_BUILD_X11 AND ARGS_LIBS MATCHES XCB::)
return()
endif()
add_executable(${ARGS_NAME} ${ARGS_SRCS})
target_link_libraries(${ARGS_NAME} KWinIntegrationTestFramework Qt::Test ${ARGS_LIBS})
if(${ARGS_BUILTIN_EFFECTS})
@ -67,8 +71,9 @@ function(integrationTest)
endif()
add_test(NAME kwin-${ARGS_NAME} COMMAND dbus-run-session ${CMAKE_BINARY_DIR}/bin/${ARGS_NAME})
endfunction()
integrationTest(NAME testDontCrashGlxgears SRCS dont_crash_glxgears.cpp LIBS KF6::I18n KDecoration2::KDecoration)
if(KWIN_BUILD_X11)
integrationTest(NAME testDontCrashGlxgears SRCS dont_crash_glxgears.cpp LIBS KF6::I18n KDecoration2::KDecoration)
endif()
if (KWIN_BUILD_SCREENLOCKER)
integrationTest(NAME testLockScreen SRCS lockscreen.cpp LIBS KF6::GlobalAccel)
endif()
@ -82,11 +87,9 @@ integrationTest(NAME testPlatformCursor SRCS platformcursor.cpp)
integrationTest(NAME testDontCrashCancelAnimation SRCS dont_crash_cancel_animation.cpp LIBS KDecoration2::KDecoration)
integrationTest(NAME testTransientPlacement SRCS transient_placement.cpp)
integrationTest(NAME testDebugConsole SRCS debug_console_test.cpp)
integrationTest(NAME testDontCrashEmptyDeco SRCS dont_crash_empty_deco.cpp LIBS KDecoration2::KDecoration)
integrationTest(NAME testPlasmaSurface SRCS plasma_surface_test.cpp)
integrationTest(NAME testMaximized SRCS maximize_test.cpp LIBS KDecoration2::KDecoration KF6::Package)
integrationTest(NAME testXdgShellWindow SRCS xdgshellwindow_test.cpp LIBS KDecoration2::KDecoration)
integrationTest(NAME testXwaylandSelections SRCS xwayland_selections_test.cpp)
integrationTest(NAME testSceneOpenGL SRCS scene_opengl_test.cpp )
integrationTest(NAME testSceneOpenGLES SRCS scene_opengl_es_test.cpp )
integrationTest(NAME testScreenChanges SRCS screen_changes_test.cpp)
@ -131,7 +134,11 @@ integrationTest(NAME testXwaylandServerRestart SRCS xwaylandserver_restart_test.
integrationTest(NAME testFakeInput SRCS fakeinput_test.cpp)
integrationTest(NAME testSecurityContext SRCS security_context_test.cpp)
integrationTest(NAME testStickyKeys SRCS sticky_keys_test.cpp)
integrationTest(NAME testXinerama SRCS xinerama_test.cpp)
if(KWIN_BUILD_X11)
integrationTest(NAME testDontCrashEmptyDeco SRCS dont_crash_empty_deco.cpp LIBS KDecoration2::KDecoration)
integrationTest(NAME testXwaylandSelections SRCS xwayland_selections_test.cpp)
integrationTest(NAME testXinerama SRCS xinerama_test.cpp)
endif()
qt_add_dbus_interfaces(DBUS_SRCS ${CMAKE_BINARY_DIR}/src/org.kde.kwin.VirtualKeyboard.xml)
integrationTest(NAME testVirtualKeyboardDBus SRCS test_virtualkeyboard_dbus.cpp ${DBUS_SRCS})

View file

@ -11,11 +11,14 @@
#include "core/output.h"
#include "debug_console.h"
#include "internalwindow.h"
#include "utils/xcbutils.h"
#include "wayland_server.h"
#include "window.h"
#include "workspace.h"
#if KWIN_BUILD_X11
#include "utils/xcbutils.h"
#endif
#include <KWayland/Client/compositor.h>
#include <KWayland/Client/connection_thread.h>
#include <KWayland/Client/shm_pool.h>
@ -38,8 +41,10 @@ private Q_SLOTS:
void cleanup();
void topLevelTest_data();
void topLevelTest();
#if KWIN_BUILD_X11
void testX11Window();
void testX11Unmanaged();
#endif
void testWaylandClient();
void testInternalWindow();
void testClosingDebugConsole();
@ -109,6 +114,7 @@ void DebugConsoleTest::topLevelTest()
}
}
#if KWIN_BUILD_X11
void DebugConsoleTest::testX11Window()
{
DebugConsoleModel model;
@ -281,6 +287,7 @@ void DebugConsoleTest::testX11Unmanaged()
QVERIFY(!model.hasChildren(unmanagedTopLevelIndex));
QVERIFY(!model2.hasChildren(model2.index(1, 0, QModelIndex())));
}
#endif
void DebugConsoleTest::testWaylandClient()
{

View file

@ -15,7 +15,9 @@
#include "wayland_server.h"
#include "window.h"
#include "workspace.h"
#if KWIN_BUILD_X11
#include "x11window.h"
#endif
#include <KDecoration2/Decoration>

View file

@ -15,11 +15,14 @@
#include "inputmethod.h"
#include "placement.h"
#include "pluginmanager.h"
#include "utils/xcbutils.h"
#include "wayland_server.h"
#include "workspace.h"
#if KWIN_BUILD_X11
#include "utils/xcbutils.h"
#include "xwayland/xwayland.h"
#include "xwayland/xwaylandlauncher.h"
#endif
#include <KPluginMetaData>
@ -99,7 +102,9 @@ WaylandTestApplication::~WaylandTestApplication()
if (effects) {
effects->unloadAllEffects();
}
#if KWIN_BUILD_X11
m_xwayland.reset();
#endif
destroyVirtualInputDevices();
destroyColorManager();
destroyWorkspace();
@ -179,10 +184,12 @@ void WaylandTestApplication::continueStartupWithScene()
qFatal("Failed to initialize the Wayland server, exiting now");
}
#if KWIN_BUILD_X11
if (operationMode() == OperationModeXwayland) {
m_xwayland = std::make_unique<Xwl::Xwayland>(this);
m_xwayland->init();
}
#endif
notifyStarted();
}
@ -202,10 +209,12 @@ Test::VirtualInputDevice *WaylandTestApplication::virtualTouch() const
return m_virtualTouch.get();
}
#if KWIN_BUILD_X11
XwaylandInterface *WaylandTestApplication::xwayland() const
{
return m_xwayland.get();
}
#endif
Test::FractionalScaleManagerV1::~FractionalScaleManagerV1()
{

View file

@ -68,10 +68,12 @@ class ScreencastingV1;
namespace KWin
{
#if KWIN_BUILD_X11
namespace Xwl
{
class Xwayland;
}
#endif
namespace Test
{
@ -93,7 +95,9 @@ public:
Test::VirtualInputDevice *virtualPointer() const;
Test::VirtualInputDevice *virtualKeyboard() const;
Test::VirtualInputDevice *virtualTouch() const;
#if KWIN_BUILD_X11
XwaylandInterface *xwayland() const override;
#endif
protected:
void performStartup() override;
@ -104,8 +108,9 @@ private:
void createVirtualInputDevices();
void destroyVirtualInputDevices();
#if KWIN_BUILD_X11
std::unique_ptr<Xwl::Xwayland> m_xwayland;
#endif
QString m_inputMethodServerToStart;
std::unique_ptr<Test::VirtualInputDevice> m_virtualPointer;
@ -766,13 +771,14 @@ bool renderNodeAvailable();
* with X on demand
*/
#if KWIN_BUILD_X11
struct XcbConnectionDeleter
{
void operator()(xcb_connection_t *pointer);
};
typedef std::unique_ptr<xcb_connection_t, XcbConnectionDeleter> XcbConnectionPtr;
XcbConnectionPtr createX11Connection();
#endif
MockInputMethod *inputMethod();
KWayland::Client::Surface *inputPanelSurface();

View file

@ -1183,6 +1183,7 @@ bool renderNodeAvailable()
});
}
#if KWIN_BUILD_X11
void XcbConnectionDeleter::operator()(xcb_connection_t *pointer)
{
xcb_disconnect(pointer);
@ -1200,6 +1201,7 @@ Test::XcbConnectionPtr createX11Connection()
e.exec();
return Test::XcbConnectionPtr(future.result());
}
#endif
WaylandOutputManagementV2::WaylandOutputManagementV2(struct ::wl_registry *registry, int id, int version)
: QObject()

View file

@ -9,12 +9,15 @@
#include "kwin_wayland_test.h"
#include "main.h"
#include "utils/xcbutils.h"
#include "virtualdesktops.h"
#include "wayland_server.h"
#include "window.h"
#include "workspace.h"
#if KWIN_BUILD_X11
#include "utils/xcbutils.h"
#endif
#include <KWayland/Client/surface.h>
using namespace KWin;
@ -28,8 +31,9 @@ private Q_SLOTS:
void initTestCase();
void init();
void cleanup();
#if KWIN_BUILD_X11
void testNetCurrentDesktop();
#endif
void testLastDesktopRemoved();
void testWindowOnMultipleDesktops();
void testRemoveDesktopWithWindow();
@ -52,6 +56,7 @@ void VirtualDesktopTest::initTestCase()
kwinApp()->start();
QVERIFY(applicationStartedSpy.wait());
#if KWIN_BUILD_X11
if (kwinApp()->x11Connection()) {
// verify the current desktop x11 property on startup, see BUG: 391034
Xcb::Atom currentDesktopAtom("_NET_CURRENT_DESKTOP");
@ -61,6 +66,7 @@ void VirtualDesktopTest::initTestCase()
QCOMPARE(currentDesktop.value(0, &ok), 0);
QVERIFY(ok);
}
#endif
}
void VirtualDesktopTest::init()
@ -75,6 +81,7 @@ void VirtualDesktopTest::cleanup()
Test::destroyWaylandConnection();
}
#if KWIN_BUILD_X11
void VirtualDesktopTest::testNetCurrentDesktop()
{
if (!kwinApp()->x11Connection()) {
@ -115,6 +122,7 @@ void VirtualDesktopTest::testNetCurrentDesktop()
QCOMPARE(currentDesktop.value(0, &ok), 0);
QVERIFY(ok);
}
#endif
void VirtualDesktopTest::testLastDesktopRemoved()
{

View file

@ -37,13 +37,11 @@ target_sources(kwin PRIVATE
3rdparty/xcursor.c
activation.cpp
appmenu.cpp
atoms.cpp
client_machine.cpp
colors/colordevice.cpp
colors/colormanager.cpp
compositor.cpp
compositor_wayland.cpp
compositor_x11.cpp
core/colorlut.cpp
core/colorlut3d.cpp
core/colorpipelinestage.cpp
@ -96,11 +94,9 @@ target_sources(kwin PRIVATE
effect/offscreenquickview.cpp
effect/quickeffect.cpp
effect/timeline.cpp
events.cpp
focuschain.cpp
ftrace.cpp
gestures.cpp
group.cpp
hide_cursor_spy.cpp
idle_inhibition.cpp
idledetector.cpp
@ -125,8 +121,6 @@ target_sources(kwin PRIVATE
main.cpp
modifier_only_shortcuts.cpp
mousebuttons.cpp
moving_client_x11_filter.cpp
netinfo.cpp
onscreennotification.cpp
opengl/abstract_opengl_context_attribute_builder.cpp
opengl/egl_context_attribute_builder.cpp
@ -160,7 +154,6 @@ target_sources(kwin PRIVATE
pointer_input.cpp
popup_input_filter.cpp
resources.qrc
rootinfo_filter.cpp
rulebooksettings.cpp
rules.cpp
scene/cursordelegate_opengl.cpp
@ -180,7 +173,6 @@ target_sources(kwin PRIVATE
scene/surfaceitem.cpp
scene/surfaceitem_internal.cpp
scene/surfaceitem_wayland.cpp
scene/surfaceitem_x11.cpp
scene/windowitem.cpp
scene/workspacescene.cpp
scene/workspacescene_opengl.cpp
@ -203,7 +195,6 @@ target_sources(kwin PRIVATE
scripting/workspace_wrapper.cpp
shadow.cpp
sm.cpp
syncalarmx11filter.cpp
tablet_input.cpp
tabletmodemanager.cpp
tiles/customtile.cpp
@ -216,16 +207,11 @@ target_sources(kwin PRIVATE
virtualdesktops.cpp
virtualdesktopsdbustypes.cpp
virtualkeyboard_dbus.cpp
was_user_interaction_x11_filter.cpp
wayland_server.cpp
waylandshellintegration.cpp
waylandwindow.cpp
window.cpp
window_property_notify_x11_filter.cpp
workspace.cpp
x11eventfilter.cpp
x11syncmanager.cpp
x11window.cpp
xdgactivationv1.cpp
xdgshellintegration.cpp
xdgshellwindow.cpp
@ -260,21 +246,6 @@ target_link_libraries(kwin
KDecoration2::KDecoration
KDecoration2::KDecoration2Private
XCB::COMPOSITE
XCB::CURSOR
XCB::DAMAGE
XCB::GLX
XCB::ICCCM
XCB::KEYSYMS
XCB::RANDR
XCB::RENDER
XCB::SHAPE
XCB::SHM
XCB::SYNC
XCB::XCB
XCB::XFIXES
XCB::XINERAMA
UDev::UDev
XKB::XKB
EGL::EGL
@ -290,6 +261,43 @@ if (TARGET K::KGlobalAccelD)
target_link_libraries(kwin PRIVATE K::KGlobalAccelD)
endif()
if (KWIN_BUILD_X11)
target_sources(kwin
PRIVATE
atoms.cpp
events.cpp
compositor_x11.cpp
group.cpp
moving_client_x11_filter.cpp
netinfo.cpp
rootinfo_filter.cpp
scene/surfaceitem_x11.cpp
syncalarmx11filter.cpp
was_user_interaction_x11_filter.cpp
window_property_notify_x11_filter.cpp
x11eventfilter.cpp
x11syncmanager.cpp
x11window.cpp
)
target_link_libraries(kwin
PRIVATE
XCB::COMPOSITE
XCB::CURSOR
XCB::DAMAGE
XCB::GLX
XCB::ICCCM
XCB::KEYSYMS
XCB::RANDR
XCB::RENDER
XCB::SHAPE
XCB::SHM
XCB::SYNC
XCB::XCB
XCB::XFIXES
XCB::XINERAMA
)
endif()
if (KWIN_BUILD_NOTIFICATIONS)
target_link_libraries(kwin PRIVATE KF6::Notifications)
endif()
@ -331,7 +339,10 @@ add_subdirectory(platformsupport)
add_subdirectory(plugins)
add_subdirectory(utils)
add_subdirectory(wayland)
add_subdirectory(xwayland)
if (KWIN_BUILD_X11)
add_subdirectory(xwayland)
endif()
if (KWIN_BUILD_ACTIVITIES)
target_sources(kwin PRIVATE activities.cpp)
@ -351,9 +362,12 @@ if (KWIN_BUILD_TABBOX)
tabbox/tabbox_logging.cpp
tabbox/tabboxconfig.cpp
tabbox/tabboxhandler.cpp
tabbox/x11_filter.cpp
)
add_subdirectory(tabbox/switchers)
if (KWIN_BUILD_X11)
target_sources(kwin PRIVATE tabbox/x11_filter.cpp)
endif()
endif()
qt_generate_dbus_interface(virtualkeyboard_dbus.h org.kde.kwin.VirtualKeyboard.xml OPTIONS -A)
@ -361,19 +375,21 @@ qt_generate_dbus_interface(tabletmodemanager.h org.kde.KWin.TabletModeManager.xm
generate_export_header(kwin EXPORT_FILE_NAME kwin_export.h)
add_executable(kwin_x11 main_x11.cpp)
target_link_libraries(kwin_x11
KWinX11Platform
kwin
KF6::GlobalAccel
)
target_compile_definitions(kwin_x11 PRIVATE
-DTRANSLATION_DOMAIN=\"kwin\"
)
kcoreaddons_target_static_plugins(kwin_x11 NAMESPACE "kwin/effects/plugins")
if (KWIN_BUILD_X11)
add_executable(kwin_x11 main_x11.cpp)
target_link_libraries(kwin_x11
KWinX11Platform
kwin
KF6::GlobalAccel
)
target_compile_definitions(kwin_x11 PRIVATE
-DTRANSLATION_DOMAIN=\"kwin\"
)
kcoreaddons_target_static_plugins(kwin_x11 NAMESPACE "kwin/effects/plugins")
install(TARGETS kwin_x11 ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
endif()
install(TARGETS kwin EXPORT KWinTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
install(TARGETS kwin_x11 ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
add_executable(kwin_wayland main_wayland.cpp)
@ -391,9 +407,12 @@ endif()
target_link_libraries(kwin_wayland
kwin
KWinXwaylandServerModule
KF6::Crash
KF6::I18n
)
if (KWIN_BUILD_X11)
target_link_libraries(kwin_wayland KWinXwaylandServerModule)
endif()
target_compile_definitions(kwin_wayland PRIVATE
-DTRANSLATION_DOMAIN=\"kwin\"
)
@ -446,12 +465,15 @@ install(
install(EXPORT KWinTargets DESTINATION "${KDE_INSTALL_CMAKEPACKAGEDIR}/KWin" FILE KWinTargets.cmake NAMESPACE KWin:: )
if (KWIN_BUILD_X11)
install(FILES atoms.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kwin COMPONENT Devel)
endif()
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/config-kwin.h
${CMAKE_CURRENT_BINARY_DIR}/kwin_export.h
activities.h
appmenu.h
atoms.h
client_machine.h
compositor.h
cursor.h

View file

@ -17,22 +17,26 @@
#include "cursor.h"
#include "focuschain.h"
#include "netinfo.h"
#include "workspace.h"
#include "x11window.h"
#if KWIN_BUILD_ACTIVITIES
#include "activities.h"
#endif
#include "virtualdesktops.h"
#include <KLocalizedString>
#include <kstartupinfo.h>
#include <kstringhandler.h>
#if KWIN_BUILD_X11
#include "atoms.h"
#include "group.h"
#include "netinfo.h"
#include "x11window.h"
#include <kstartupinfo.h>
#endif
#include <KLocalizedString>
#include <kstringhandler.h>
#include "rules.h"
#include "useractions.h"
#include "window.h"
#include <QDebug>
namespace KWin
@ -259,9 +263,11 @@ void Workspace::setActiveWindow(Window *window)
updateStackingOrder(); // e.g. fullscreens have different layer when active/not-active
#if KWIN_BUILD_X11
if (rootInfo()) {
rootInfo()->setActiveClient(m_activeWindow);
}
#endif
Q_EMIT windowActivated(m_activeWindow);
--m_setActiveWindowRecursion;
@ -330,6 +336,7 @@ void Workspace::activateWindow(Window *window, bool force)
requestFocus(window, force);
}
#if KWIN_BUILD_X11
// Don't update user time for windows that have focus stealing workaround.
// As they usually belong to the current active window but fail to provide
// this information, updating their user time would make the user time
@ -341,6 +348,7 @@ void Workspace::activateWindow(Window *window, bool force)
// updateUserTime is X11 specific
x11Window->updateUserTime();
}
#endif
m_quickTileCombineTimer->stop();
}
@ -558,7 +566,7 @@ void Workspace::setShouldGetFocus(Window *window)
// a window to be fully raised upon its own request (XRaiseWindow),
// if refused, it will be raised only on top of windows belonging
// to the same application
bool Workspace::allowFullClientRaising(const KWin::Window *window, xcb_timestamp_t time)
bool Workspace::allowFullClientRaising(const KWin::Window *window, uint32_t time)
{
int level = window->rules()->checkFSP(options->focusStealingPreventionLevel());
if (sessionManager()->state() == SessionState::Saving && level <= 2) { // <= normal
@ -583,10 +591,14 @@ bool Workspace::allowFullClientRaising(const KWin::Window *window, xcb_timestamp
if (level == 3) { // high
return false;
}
#if KWIN_BUILD_X11
xcb_timestamp_t user_time = ac->userTime();
qCDebug(KWIN_CORE) << "Raising, compared:" << time << ":" << user_time
<< ":" << (NET::timestampCompare(time, user_time) >= 0);
return NET::timestampCompare(time, user_time) >= 0; // time >= user_time
#else
return true;
#endif
}
/**
@ -601,7 +613,9 @@ bool Workspace::restoreFocus()
// a timestamp *sigh*, kwin's timestamp would be older than the timestamp
// that was used by whoever caused the focus change, and therefore
// the attempt to restore the focus would fail due to old timestamp
#if KWIN_BUILD_X11
kwinApp()->updateXTime();
#endif
if (should_get_focus.count() > 0) {
return requestFocus(should_get_focus.last());
} else if (m_lastActiveWindow) {
@ -620,312 +634,4 @@ void Workspace::windowAttentionChanged(Window *window, bool set)
}
}
//********************************************
// Client
//********************************************
/**
* Updates the user time (time of last action in the active window).
* This is called inside kwin for every action with the window
* that qualifies for user interaction (clicking on it, activate it
* externally, etc.).
*/
void X11Window::updateUserTime(xcb_timestamp_t time)
{
// copied in Group::updateUserTime
if (time == XCB_TIME_CURRENT_TIME) {
kwinApp()->updateXTime();
time = xTime();
}
if (time != -1U
&& (m_userTime == XCB_TIME_CURRENT_TIME
|| NET::timestampCompare(time, m_userTime) > 0)) { // time > user_time
m_userTime = time;
shade_below = nullptr; // do not hover re-shade a window after it got interaction
}
group()->updateUserTime(m_userTime);
}
xcb_timestamp_t X11Window::readUserCreationTime() const
{
Xcb::Property prop(false, window(), atoms->kde_net_wm_user_creation_time, XCB_ATOM_CARDINAL, 0, 1);
return prop.value<xcb_timestamp_t>(-1);
}
xcb_timestamp_t X11Window::readUserTimeMapTimestamp(const KStartupInfoId *asn_id, const KStartupInfoData *asn_data,
bool session) const
{
xcb_timestamp_t time = info->userTime();
// qDebug() << "User timestamp, initial:" << time;
//^^ this deadlocks kwin --replace sometimes.
// newer ASN timestamp always replaces user timestamp, unless user timestamp is 0
// helps e.g. with konqy reusing
if (asn_data != nullptr && time != 0) {
if (asn_id->timestamp() != 0
&& (time == -1U || NET::timestampCompare(asn_id->timestamp(), time) > 0)) {
time = asn_id->timestamp();
}
}
qCDebug(KWIN_CORE) << "User timestamp, ASN:" << time;
if (time == -1U) {
// The window doesn't have any timestamp.
// If it's the first window for its application
// (i.e. there's no other window from the same app),
// use the _KDE_NET_WM_USER_CREATION_TIME trick.
// Otherwise, refuse activation of a window
// from already running application if this application
// is not the active one (unless focus stealing prevention is turned off).
X11Window *act = dynamic_cast<X11Window *>(workspace()->mostRecentlyActivatedWindow());
if (act != nullptr && !belongToSameApplication(act, this, SameApplicationCheck::RelaxedForActive)) {
bool first_window = true;
auto sameApplicationActiveHackPredicate = [this](const X11Window *cl) {
// ignore already existing splashes, toolbars, utilities and menus,
// as the app may show those before the main window
return !cl->isSplash() && !cl->isToolbar() && !cl->isUtility() && !cl->isMenu()
&& cl != this && X11Window::belongToSameApplication(cl, this, SameApplicationCheck::RelaxedForActive);
};
if (isTransient()) {
auto clientMainClients = [this]() {
QList<X11Window *> ret;
const auto mcs = mainWindows();
for (auto mc : mcs) {
if (X11Window *c = dynamic_cast<X11Window *>(mc)) {
ret << c;
}
}
return ret;
};
if (act->hasTransient(this, true)) {
; // is transient for currently active window, even though it's not
// the same app (e.g. kcookiejar dialog) -> allow activation
} else if (groupTransient() && findInList<X11Window, X11Window>(clientMainClients(), sameApplicationActiveHackPredicate) == nullptr) {
; // standalone transient
} else {
first_window = false;
}
} else {
if (workspace()->findClient(sameApplicationActiveHackPredicate)) {
first_window = false;
}
}
// don't refuse if focus stealing prevention is turned off
if (!first_window && rules()->checkFSP(options->focusStealingPreventionLevel()) > 0) {
qCDebug(KWIN_CORE) << "User timestamp, already exists:" << 0;
return 0; // refuse activation
}
}
// Creation time would just mess things up during session startup,
// as possibly many apps are started up at the same time.
// If there's no active window yet, no timestamp will be needed,
// as plain Workspace::allowWindowActivation() will return true
// in such case. And if there's already active window,
// it's better not to activate the new one.
// Unless it was the active window at the time
// of session saving and there was no user interaction yet,
// this check will be done in manage().
if (session) {
return -1U;
}
time = readUserCreationTime();
}
qCDebug(KWIN_CORE) << "User timestamp, final:" << this << ":" << time;
return time;
}
xcb_timestamp_t X11Window::userTime() const
{
xcb_timestamp_t time = m_userTime;
if (time == 0) { // doesn't want focus after showing
return 0;
}
Q_ASSERT(group() != nullptr);
if (time == -1U
|| (group()->userTime() != -1U
&& NET::timestampCompare(group()->userTime(), time) > 0)) {
time = group()->userTime();
}
return time;
}
void X11Window::doSetActive()
{
updateUrgency(); // demand attention again if it's still urgent
info->setState(isActive() ? NET::Focused : NET::States(), NET::Focused);
}
void X11Window::startupIdChanged()
{
KStartupInfoId asn_id;
KStartupInfoData asn_data;
bool asn_valid = workspace()->checkStartupNotification(window(), asn_id, asn_data);
if (!asn_valid) {
return;
}
// If the ASN contains desktop, move it to the desktop, otherwise move it to the current
// desktop (since the new ASN should make the window act like if it's a new application
// launched). However don't affect the window's desktop if it's set to be on all desktops.
if (asn_data.desktop() != 0 && !isOnAllDesktops()) {
if (asn_data.desktop() == -1) {
workspace()->sendWindowToDesktops(this, {}, true);
} else {
if (VirtualDesktop *desktop = VirtualDesktopManager::self()->desktopForX11Id(asn_data.desktop())) {
workspace()->sendWindowToDesktops(this, {desktop}, true);
}
}
}
if (asn_data.xinerama() != -1) {
Output *output = workspace()->xineramaIndexToOutput(asn_data.xinerama());
if (output) {
workspace()->sendWindowToOutput(this, output);
}
}
const xcb_timestamp_t timestamp = asn_id.timestamp();
if (timestamp != 0) {
bool activate = allowWindowActivation(timestamp);
if (activate) {
workspace()->activateWindow(this);
} else {
demandAttention();
}
}
}
void X11Window::updateUrgency()
{
if (info->urgency()) {
demandAttention();
}
}
namespace FSP
{
enum Level {
None = 0,
Low,
Medium,
High,
Extreme,
};
}
// focus_in -> the window got FocusIn event
bool X11Window::allowWindowActivation(xcb_timestamp_t time, bool focus_in)
{
auto window = this;
// options->focusStealingPreventionLevel :
// 0 - none - old KWin behaviour, new windows always get focus
// 1 - low - focus stealing prevention is applied normally, when unsure, activation is allowed
// 2 - normal - focus stealing prevention is applied normally, when unsure, activation is not allowed,
// this is the default
// 3 - high - new window gets focus only if it belongs to the active application,
// or when no window is currently active
// 4 - extreme - no window gets focus without user intervention
if (time == -1U) {
time = window->userTime();
}
const FSP::Level level = (FSP::Level)window->rules()->checkFSP(options->focusStealingPreventionLevel());
if (workspace()->sessionManager()->state() == SessionState::Saving && level <= FSP::Medium) { // <= normal
return true;
}
Window *ac = workspace()->mostRecentlyActivatedWindow();
if (focus_in) {
if (workspace()->inShouldGetFocus(window)) {
return true; // FocusIn was result of KWin's action
}
// Before getting FocusIn, the active Client already
// got FocusOut, and therefore got deactivated.
ac = workspace()->lastActiveWindow();
}
if (time == 0) { // explicitly asked not to get focus
if (!window->rules()->checkAcceptFocus(false)) {
return false;
}
}
const FSP::Level protection = (FSP::Level)(ac ? ac->rules()->checkFPP(2) : FSP::None);
// stealing is unconditionally allowed (NETWM behavior)
if (level == FSP::None || protection == FSP::None) {
return true;
}
// The active window "grabs" the focus or stealing is generally forbidden
if (level == FSP::Extreme || protection == FSP::Extreme) {
return false;
}
// No active window, it's ok to pass focus
// NOTICE that extreme protection needs to be handled before to allow protection on unmanged windows
if (ac == nullptr || ac->isDesktop()) {
qCDebug(KWIN_CORE) << "Activation: No window active, allowing";
return true; // no active window -> always allow
}
// TODO window urgency -> return true?
// Unconditionally allow intra-window passing around for lower stealing protections
// unless the active window has High interest
if (Window::belongToSameApplication(window, ac, Window::SameApplicationCheck::RelaxedForActive) && protection < FSP::High) {
qCDebug(KWIN_CORE) << "Activation: Belongs to active application";
return true;
}
// High FPS, not intr-window change. Only allow if the active window has only minor interest
if (level > FSP::Medium && protection > FSP::Low) {
return false;
}
if (time == -1U) { // no time known
qCDebug(KWIN_CORE) << "Activation: No timestamp at all";
// Only allow for Low protection unless active window has High interest in focus
if (level < FSP::Medium && protection < FSP::High) {
return true;
}
// no timestamp at all, don't activate - because there's also creation timestamp
// done on CreateNotify, this case should happen only in case application
// maps again already used window, i.e. this won't happen after app startup
return false;
}
// Low or medium FSP, usertime comparism is possible
const xcb_timestamp_t user_time = ac->userTime();
qCDebug(KWIN_CORE) << "Activation, compared:" << window << ":" << time << ":" << user_time
<< ":" << (NET::timestampCompare(time, user_time) >= 0);
return NET::timestampCompare(time, user_time) >= 0; // time >= user_time
}
//****************************************
// Group
//****************************************
void Group::startupIdChanged()
{
KStartupInfoId asn_id;
KStartupInfoData asn_data;
bool asn_valid = workspace()->checkStartupNotification(leader_wid, asn_id, asn_data);
if (!asn_valid) {
return;
}
if (asn_id.timestamp() != 0 && user_time != -1U
&& NET::timestampCompare(asn_id.timestamp(), user_time) > 0) {
user_time = asn_id.timestamp();
}
}
void Group::updateUserTime(xcb_timestamp_t time)
{
// copy of X11Window::updateUserTime
if (time == XCB_CURRENT_TIME) {
kwinApp()->updateXTime();
time = xTime();
}
if (time != -1U
&& (user_time == XCB_CURRENT_TIME
|| NET::timestampCompare(time, user_time) > 0)) { // time > user_time
user_time = time;
}
}
} // namespace

View file

@ -8,8 +8,11 @@
*/
#include "activities.h"
// KWin
#include "window.h"
#include "workspace.h"
#if KWIN_BUILD_X11
#include "x11window.h"
#endif
// KDE
#include <KConfigGroup>
// Qt
@ -173,6 +176,7 @@ void Activities::reallyStop(const QString &id)
QSet<QByteArray> saveSessionIds;
QSet<QByteArray> dontCloseSessionIds;
#if KWIN_BUILD_X11
const auto windows = ws->windows();
for (auto *const window : windows) {
auto x11Window = qobject_cast<X11Window *>(window);
@ -206,8 +210,8 @@ void Activities::reallyStop(const QString &id)
}
}
}
ws->sessionManager()->storeSubSession(id, saveSessionIds);
#endif
QStringList saveAndClose;
QStringList saveOnly;

View file

@ -9,8 +9,8 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "appmenu.h"
#include "window.h"
#include "workspace.h"
#include "x11window.h"
#include <appmenu_interface.h>
#include <QDBusObjectPath>

View file

@ -11,8 +11,6 @@
#pragma once
// Qt
#include <QObject>
// xcb
#include <xcb/xcb.h>
class QPoint;
class OrgKdeKappmenuInterface;

View file

@ -11,6 +11,12 @@
#pragma once
#include "config-kwin.h"
#if !KWIN_BUILD_X11
#error Do not include on non-X11 builds
#endif
#include "utils/xcbutils.h"
namespace KWin

View file

@ -3,4 +3,7 @@ add_subdirectory(fakeinput)
add_subdirectory(libinput)
add_subdirectory(virtual)
add_subdirectory(wayland)
add_subdirectory(x11)
if (KWIN_BUILD_X11)
add_subdirectory(x11)
endif()

View file

@ -8,11 +8,17 @@
*/
// own
#include "client_machine.h"
#include "effect/xcb.h"
#include "main.h"
#include "utils/common.h"
#if KWIN_BUILD_X11
#include "effect/xcb.h"
#endif
// KF5
#if KWIN_BUILD_X11
#include <NETWM>
#endif
// Qt
#include <QFutureWatcher>
#include <QtConcurrentRun>
@ -167,6 +173,7 @@ ClientMachine::~ClientMachine()
{
}
#if KWIN_BUILD_X11
void ClientMachine::resolve(xcb_window_t window, xcb_window_t clientLeader)
{
if (m_resolved) {
@ -186,6 +193,7 @@ void ClientMachine::resolve(xcb_window_t window, xcb_window_t clientLeader)
checkForLocalhost();
m_resolved = true;
}
#endif
void ClientMachine::checkForLocalhost()
{

View file

@ -8,9 +8,13 @@
*/
#pragma once
#include "config-kwin.h"
#include <QObject>
#include <memory>
#if KWIN_BUILD_X11
#include <xcb/xcb.h>
#endif
// forward declaration
struct addrinfo;
@ -57,7 +61,9 @@ public:
explicit ClientMachine(QObject *parent = nullptr);
~ClientMachine() override;
#if KWIN_BUILD_X11
void resolve(xcb_window_t window, xcb_window_t clientLeader);
#endif
const QString &hostName() const;
bool isLocal() const;
static QString localhost();

View file

@ -45,14 +45,14 @@ Compositor *Compositor::self()
Compositor::Compositor(QObject *workspace)
: QObject(workspace)
{
#if KWIN_BUILD_X11
// 2 sec which should be enough to restart the compositor.
static const int compositorLostMessageDelay = 2000;
m_unusedSupportPropertyTimer.setInterval(compositorLostMessageDelay);
m_unusedSupportPropertyTimer.setSingleShot(true);
connect(&m_unusedSupportPropertyTimer, &QTimer::timeout,
this, &Compositor::deleteUnusedSupportProperties);
#endif
// Delay the call to start by one event cycle.
// The ctor of this class is invoked from the Workspace ctor, that means before
// Workspace is completely constructed, so calling Workspace::self() would result
@ -66,7 +66,9 @@ Compositor::Compositor(QObject *workspace)
Compositor::~Compositor()
{
#if KWIN_BUILD_X11
deleteUnusedSupportProperties();
#endif
s_compositor = nullptr;
}
@ -94,6 +96,7 @@ void Compositor::removeSuperLayer(RenderLayer *layer)
delete layer;
}
#if KWIN_BUILD_X11
void Compositor::keepSupportProperty(xcb_atom_t atom)
{
m_unusedSupportProperties.removeAll(atom);
@ -120,6 +123,7 @@ void Compositor::deleteUnusedSupportProperties()
m_unusedSupportProperties.clear();
}
}
#endif
void Compositor::reinitialize()
{

View file

@ -9,8 +9,12 @@
*/
#pragma once
#include "config-kwin.h"
#include <kwin_export.h>
#if KWIN_BUILD_X11
#include <xcb/xcb.h>
#endif
#include <QHash>
#include <QObject>
@ -80,9 +84,11 @@ public:
return s_compositor != nullptr && s_compositor->isActive();
}
#if KWIN_BUILD_X11
// for delayed supportproperty management of effects
void keepSupportProperty(xcb_atom_t atom);
void removeSupportProperty(xcb_atom_t atom);
#endif
/**
* Whether Compositing is possible in the Platform.
@ -134,7 +140,9 @@ private Q_SLOTS:
void handleFrameRequested(RenderLoop *renderLoop);
protected:
#if KWIN_BUILD_X11
void deleteUnusedSupportProperties();
#endif
Output *findOutput(RenderLoop *loop) const;
@ -147,8 +155,10 @@ protected:
void framePass(RenderLayer *layer, OutputFrame *frame);
State m_state = State::Off;
#if KWIN_BUILD_X11
QList<xcb_atom_t> m_unusedSupportProperties;
QTimer m_unusedSupportPropertyTimer;
#endif
std::unique_ptr<WorkspaceScene> m_scene;
std::unique_ptr<CursorScene> m_cursorScene;
std::unique_ptr<RenderBackend> m_backend;

View file

@ -10,6 +10,7 @@
#cmakedefine01 KWIN_BUILD_TABBOX
#cmakedefine01 KWIN_BUILD_ACTIVITIES
#cmakedefine01 KWIN_BUILD_GLOBALSHORTCUTS
#cmakedefine01 KWIN_BUILD_X11
constexpr QLatin1String KWIN_CONFIG("kwinrc");
constexpr QLatin1String KWIN_VERSION_STRING("${PROJECT_VERSION}");
constexpr QLatin1String XCB_VERSION_STRING("${XCB_VERSION}");

View file

@ -17,7 +17,10 @@
#include "main.h"
#include "scene/workspacescene.h"
#include "utils/common.h"
#if KWIN_BUILD_X11
#include "utils/xcbutils.h"
#endif
// KDE
#include <KConfig>
#include <KConfigGroup>
@ -222,6 +225,7 @@ void Cursor::markAsRendered(std::chrono::milliseconds timestamp)
Q_EMIT rendered(timestamp);
}
#if KWIN_BUILD_X11
xcb_cursor_t Cursor::x11Cursor(CursorShape shape)
{
return x11Cursor(shape.name());
@ -261,6 +265,7 @@ xcb_cursor_t Cursor::x11Cursor(const QByteArray &name)
xcb_cursor_context_free(ctx);
return cursor;
}
#endif
void Cursor::doSetPos()
{

View file

@ -32,15 +32,16 @@
#include "wayland_server.h"
#include "waylandwindow.h"
#include "workspace.h"
#include "x11window.h"
#include "xkb.h"
#include <cerrno>
#if KWIN_BUILD_X11
#include "x11window.h"
#endif
#include "ui_debug_console.h"
// frameworks
#include <KLocalizedString>
#include <NETWM>
// Qt
#include <QFutureWatcher>
#include <QMetaProperty>
@ -48,6 +49,7 @@
#include <QMouseEvent>
#include <QScopeGuard>
#include <QSortFilterProxyModel>
#include <QWindow>
#include <QtConcurrentRun>
#include <wayland-server-core.h>
@ -932,6 +934,7 @@ DebugConsoleModel::DebugConsoleModel(QObject *parent)
void DebugConsoleModel::handleWindowAdded(Window *window)
{
#if KWIN_BUILD_X11
if (auto x11 = qobject_cast<X11Window *>(window)) {
if (x11->isUnmanaged()) {
add(s_x11UnmanagedId - 1, m_unmanageds, x11);
@ -940,6 +943,7 @@ void DebugConsoleModel::handleWindowAdded(Window *window)
}
return;
}
#endif
if (auto wayland = qobject_cast<WaylandWindow *>(window)) {
add(s_waylandWindowId - 1, m_waylandWindows, wayland);
@ -954,6 +958,7 @@ void DebugConsoleModel::handleWindowAdded(Window *window)
void DebugConsoleModel::handleWindowRemoved(Window *window)
{
#if KWIN_BUILD_X11
if (auto x11 = qobject_cast<X11Window *>(window)) {
if (x11->isUnmanaged()) {
remove(s_x11UnmanagedId - 1, m_unmanageds, x11);
@ -962,6 +967,7 @@ void DebugConsoleModel::handleWindowRemoved(Window *window)
}
return;
}
#endif
if (auto wayland = qobject_cast<WaylandWindow *>(window)) {
remove(s_waylandWindowId - 1, m_waylandWindows, wayland);
@ -1020,9 +1026,17 @@ int DebugConsoleModel::rowCount(const QModelIndex &parent) const
}
if (parent.internalId() < s_idDistance * (s_x11WindowId + 1)) {
#if KWIN_BUILD_X11
return propertyCount(parent, &DebugConsoleModel::x11Window);
#else
return 0;
#endif
} else if (parent.internalId() < s_idDistance * (s_x11UnmanagedId + 1)) {
#if KWIN_BUILD_X11
return propertyCount(parent, &DebugConsoleModel::unmanaged);
#else
return 0;
#endif
} else if (parent.internalId() < s_idDistance * (s_waylandWindowId + 1)) {
return propertyCount(parent, &DebugConsoleModel::waylandWindow);
} else if (parent.internalId() < s_idDistance * (s_workspaceInternalId + 1)) {
@ -1085,9 +1099,17 @@ QModelIndex DebugConsoleModel::index(int row, int column, const QModelIndex &par
// index for a property (third level)
if (parent.internalId() < s_idDistance * (s_x11WindowId + 1)) {
#if KWIN_BUILD_X11
return indexForProperty(row, column, parent, &DebugConsoleModel::x11Window);
#else
return {};
#endif
} else if (parent.internalId() < s_idDistance * (s_x11UnmanagedId + 1)) {
#if KWIN_BUILD_X11
return indexForProperty(row, column, parent, &DebugConsoleModel::unmanaged);
#else
return {};
#endif
} else if (parent.internalId() < s_idDistance * (s_waylandWindowId + 1)) {
return indexForProperty(row, column, parent, &DebugConsoleModel::waylandWindow);
} else if (parent.internalId() < s_idDistance * (s_workspaceInternalId + 1)) {
@ -1233,10 +1255,12 @@ QVariant DebugConsoleModel::data(const QModelIndex &index, int role) const
return propertyData(w, index, role);
} else if (InternalWindow *w = internalWindow(index)) {
return propertyData(w, index, role);
#if KWIN_BUILD_X11
} else if (X11Window *w = x11Window(index)) {
return propertyData(w, index, role);
} else if (X11Window *u = unmanaged(index)) {
return propertyData(u, index, role);
#endif
}
} else {
if (index.column() != 0) {
@ -1248,10 +1272,14 @@ QVariant DebugConsoleModel::data(const QModelIndex &index, int role) const
};
switch (index.parent().internalId()) {
case s_x11WindowId:
#if KWIN_BUILD_X11
return windowData<X11Window>(index, role, m_x11Windows, [](X11Window *c) -> QString {
return QStringLiteral("0x%1: %2").arg(c->window(), 0, 16).arg(c->caption());
});
#endif
break;
case s_x11UnmanagedId: {
#if KWIN_BUILD_X11
if (index.row() >= m_unmanageds.count()) {
return QVariant();
}
@ -1259,6 +1287,7 @@ QVariant DebugConsoleModel::data(const QModelIndex &index, int role) const
if (role == Qt::DisplayRole) {
return QStringLiteral("0x%1").arg(u->window(), 0, 16);
}
#endif
break;
}
case s_waylandWindowId:

View file

@ -12,7 +12,9 @@
#include "decorationpalette.h"
#include "window.h"
#include "workspace.h"
#if KWIN_BUILD_X11
#include "x11window.h"
#endif
#include <KDecoration2/DecoratedClient>
#include <KDecoration2/Decoration>
@ -136,17 +138,21 @@ DELEGATE(bool, isShaded, isShade)
WId DecoratedClientImpl::windowId() const
{
#if KWIN_BUILD_X11
if (X11Window *x11Window = qobject_cast<X11Window *>(m_window)) {
return x11Window->window();
}
#endif
return 0;
}
WId DecoratedClientImpl::decorationId() const
{
#if KWIN_BUILD_X11
if (X11Window *x11Window = qobject_cast<X11Window *>(m_window)) {
return x11Window->frameId();
}
#endif
return 0;
}

View file

@ -42,8 +42,9 @@
#include "wayland_server.h"
#include "window_property_notify_x11_filter.h"
#include "workspace.h"
#if KWIN_BUILD_X11
#include "x11window.h"
#endif
#if KWIN_BUILD_ACTIVITIES
#include "activities.h"
#endif
@ -68,7 +69,7 @@
namespace KWin
{
#if KWIN_BUILD_X11
static QByteArray readWindowProperty(xcb_window_t win, xcb_atom_t atom, xcb_atom_t type, int format)
{
if (win == XCB_WINDOW_NONE) {
@ -108,6 +109,7 @@ static xcb_atom_t registerSupportProperty(const QByteArray &propertyName)
// TODO: add to _NET_SUPPORTED
return atomReply->atom;
}
#endif
//****************************************
// EffectsHandler
@ -200,6 +202,7 @@ EffectsHandler::EffectsHandler(Compositor *compositor, WorkspaceScene *scene)
connect(kwinApp()->screenLockerWatcher(), &ScreenLockerWatcher::aboutToLock, this, &EffectsHandler::screenAboutToLock);
#endif
#if KWIN_BUILD_X11
connect(kwinApp(), &Application::x11ConnectionChanged, this, [this]() {
registered_atoms.clear();
for (auto it = m_propertiesForEffects.keyBegin(); it != m_propertiesForEffects.keyEnd(); it++) {
@ -222,6 +225,7 @@ EffectsHandler::EffectsHandler(Compositor *compositor, WorkspaceScene *scene)
if (kwinApp()->x11Connection()) {
m_x11WindowPropertyNotify = std::make_unique<WindowPropertyNotifyX11Filter>(this);
}
#endif
// connect all clients
for (Window *window : ws->windows()) {
@ -244,6 +248,7 @@ EffectsHandler::~EffectsHandler()
KWin::effects = nullptr;
}
#if KWIN_BUILD_X11
xcb_window_t EffectsHandler::x11RootWindow() const
{
return kwinApp()->x11RootWindow();
@ -253,6 +258,7 @@ xcb_connection_t *EffectsHandler::xcbConnection() const
{
return kwinApp()->x11Connection();
}
#endif
CompositingType EffectsHandler::compositingType() const
{
@ -638,6 +644,7 @@ bool EffectsHandler::hasKeyboardGrab() const
return keyboard_grab_effect != nullptr;
}
#if KWIN_BUILD_X11
void EffectsHandler::registerPropertyType(long atom, bool reg)
{
if (reg) {
@ -692,13 +699,18 @@ void EffectsHandler::removeSupportProperty(const QByteArray &propertyName, Effec
m_propertiesForEffects.remove(propertyName);
m_compositor->removeSupportProperty(atom); // delayed removal
}
#endif
QByteArray EffectsHandler::readRootProperty(long atom, long type, int format) const
{
#if KWIN_BUILD_X11
if (!kwinApp()->x11Connection()) {
return QByteArray();
}
return readWindowProperty(kwinApp()->x11RootWindow(), atom, type, format);
#else
return {};
#endif
}
void EffectsHandler::activateWindow(EffectWindow *effectWindow)
@ -859,15 +871,16 @@ double EffectsHandler::animationTimeFactor() const
EffectWindow *EffectsHandler::findWindow(WId id) const
{
#if KWIN_BUILD_X11
if (X11Window *w = Workspace::self()->findClient(Predicate::WindowMatch, id)) {
return w->effectWindow();
}
if (X11Window *w = Workspace::self()->findUnmanaged(id)) {
return w->effectWindow();
}
#endif
return nullptr;
}
EffectWindow *EffectsHandler::findWindow(SurfaceInterface *surf) const
{
if (waylandServer()) {
@ -1197,10 +1210,12 @@ void EffectsHandler::destroyEffect(Effect *effect)
stopMouseInterception(effect);
#if KWIN_BUILD_X11
const QList<QByteArray> properties = m_propertiesForEffects.keys();
for (const QByteArray &property : properties) {
removeSupportProperty(property, effect);
}
#endif
delete effect;
}

View file

@ -12,6 +12,7 @@
#pragma once
#include "config-kwin.h"
#include "effect/effect.h"
#include "effect/effectwindow.h"
@ -29,7 +30,9 @@
#include <functional>
#if KWIN_BUILD_X11
#include <xcb/xcb.h>
#endif
class KConfigGroup;
class QFont;
@ -480,6 +483,8 @@ public:
void reconfigure();
QByteArray readRootProperty(long atom, long type, int format) const;
#if KWIN_BUILD_X11
/**
* @brief Announces support for the feature with the given name. If no other Effect
* has announced support for this feature yet, an X11 property will be installed on
@ -511,6 +516,7 @@ public:
* @since 4.11
*/
void removeSupportProperty(const QByteArray &propertyName, Effect *effect);
#endif
/**
* Returns @a true if the active window decoration has shadow API hooks.
@ -570,8 +576,10 @@ public:
*/
void doneOpenGLContextCurrent();
#if KWIN_BUILD_X11
xcb_connection_t *xcbConnection() const;
xcb_window_t x11RootWindow() const;
#endif
/**
* Interface to the Wayland display: this is relevant only
@ -741,10 +749,12 @@ public:
void highlightWindows(const QList<EffectWindow *> &windows);
#if KWIN_BUILD_X11
bool isPropertyTypeRegistered(xcb_atom_t atom) const
{
return registered_atoms.contains(atom);
}
#endif
Q_SIGNALS:
/**
@ -987,6 +997,7 @@ Q_SIGNALS:
*/
void windowDataChanged(KWin::EffectWindow *w, int role);
#if KWIN_BUILD_X11
/**
* The xcb connection changed, either a new xcbConnection got created or the existing one
* got destroyed.
@ -998,6 +1009,7 @@ Q_SIGNALS:
* @since 5.11
*/
void xcbConnectionChanged();
#endif
/**
* This signal is emitted when active fullscreen effect changed.
@ -1082,7 +1094,9 @@ protected:
Effect *keyboard_grab_effect;
Effect *fullscreen_effect;
QMultiMap<int, EffectPair> effect_order;
#if KWIN_BUILD_X11
QHash<long, int> registered_atoms;
#endif
QList<EffectPair> loaded_effects;
CompositingType compositing_type;
EffectsList m_activeEffects;
@ -1090,7 +1104,9 @@ protected:
EffectsIterator m_currentPaintWindowIterator;
EffectsIterator m_currentPaintScreenIterator;
typedef QHash<QByteArray, QList<Effect *>> PropertyEffectMap;
#if KWIN_BUILD_X11
PropertyEffectMap m_propertiesForEffects;
#endif
QHash<QByteArray, qulonglong> m_managedProperties;
Compositor *m_compositor;
WorkspaceScene *m_scene;

View file

@ -10,12 +10,15 @@
#include "effect/effectwindow.h"
#include "core/output.h"
#include "effect/effecthandler.h"
#include "group.h"
#include "internalwindow.h"
#include "scene/windowitem.h"
#include "virtualdesktops.h"
#include "waylandwindow.h"
#if KWIN_BUILD_X11
#include "group.h"
#include "x11window.h"
#endif
namespace KWin
{
@ -54,7 +57,11 @@ EffectWindow::EffectWindow(WindowItem *windowItem)
d->managed = d->m_window->isClient();
d->m_waylandWindow = qobject_cast<KWin::WaylandWindow *>(d->m_window) != nullptr;
#if KWIN_BUILD_X11
d->m_x11Window = qobject_cast<KWin::X11Window *>(d->m_window) != nullptr;
#else
d->m_x11Window = false;
#endif
connect(d->m_window, &Window::hiddenChanged, this, [this]() {
Q_EMIT windowHiddenChanged(this);
@ -210,9 +217,11 @@ void EffectWindow::addLayerRepaint(const QRect &r)
const EffectWindowGroup *EffectWindow::group() const
{
#if KWIN_BUILD_X11
if (Group *group = d->m_window->group()) {
return group->effectGroup();
}
#endif
return nullptr;
}
@ -302,9 +311,11 @@ WINDOW_HELPER(bool, isInputMethod, isInputMethod)
qlonglong EffectWindow::windowId() const
{
#if KWIN_BUILD_X11
if (X11Window *x11Window = qobject_cast<X11Window *>(d->m_window)) {
return x11Window->window();
}
#endif
return 0;
}
@ -325,9 +336,11 @@ WindowType EffectWindow::windowType() const
QSizeF EffectWindow::basicUnit() const
{
#if KWIN_BUILD_X11
if (auto window = qobject_cast<X11Window *>(d->m_window)) {
return window->basicUnit();
}
#endif
return QSize(1, 1);
}
@ -343,6 +356,7 @@ KDecoration2::Decoration *EffectWindow::decoration() const
QByteArray EffectWindow::readProperty(long atom, long type, int format) const
{
#if KWIN_BUILD_X11
auto x11Window = qobject_cast<X11Window *>(d->m_window);
if (!x11Window) {
return QByteArray();
@ -363,10 +377,13 @@ QByteArray EffectWindow::readProperty(long atom, long type, int format) const
}
return prop.toByteArray(format, type);
}
#endif
return {};
}
void EffectWindow::deleteProperty(long int atom) const
{
#if KWIN_BUILD_X11
auto x11Window = qobject_cast<X11Window *>(d->m_window);
if (!x11Window) {
return;
@ -375,6 +392,7 @@ void EffectWindow::deleteProperty(long int atom) const
return;
}
xcb_delete_property(kwinApp()->x11Connection(), x11Window->window(), atom);
#endif
}
EffectWindow *EffectWindow::findModal()
@ -495,12 +513,14 @@ EffectWindowGroup::~EffectWindowGroup()
QList<EffectWindow *> EffectWindowGroup::members() const
{
const auto memberList = m_group->members();
QList<EffectWindow *> ret;
#if KWIN_BUILD_X11
const auto memberList = m_group->members();
ret.reserve(memberList.size());
std::transform(std::cbegin(memberList), std::cend(memberList), std::back_inserter(ret), [](auto window) {
return window->effectWindow();
});
#endif
return ret;
}

View file

@ -9,11 +9,13 @@
#pragma once
#include "core/output.h"
#include "kwin_export.h"
#include "globals.h"
#include <QObject>
#include <QWindow>
class QWindow;

View file

@ -8,6 +8,11 @@
*/
#pragma once
#include "config-kwin.h"
#if !KWIN_BUILD_X11
#error Do not include on non-X11 builds
#endif
#include <QGuiApplication>
#include <kwin_export.h>

View file

@ -13,6 +13,7 @@
#include "workspace.h"
#include "x11window.h"
#include <KStartupInfo>
#include <KX11Extras>
#include <QDebug>
@ -116,4 +117,32 @@ void Group::lostLeader()
}
}
void Group::startupIdChanged()
{
KStartupInfoId asn_id;
KStartupInfoData asn_data;
bool asn_valid = workspace()->checkStartupNotification(leader_wid, asn_id, asn_data);
if (!asn_valid) {
return;
}
if (asn_id.timestamp() != 0 && user_time != -1U
&& NET::timestampCompare(asn_id.timestamp(), user_time) > 0) {
user_time = asn_id.timestamp();
}
}
void Group::updateUserTime(xcb_timestamp_t time)
{
// copy of X11Window::updateUserTime
if (time == XCB_CURRENT_TIME) {
kwinApp()->updateXTime();
time = xTime();
}
if (time != -1U
&& (user_time == XCB_CURRENT_TIME
|| NET::timestampCompare(time, user_time) > 0)) { // time > user_time
user_time = time;
}
}
} // namespace

View file

@ -10,6 +10,11 @@
#pragma once
#include <config-kwin.h>
#if !KWIN_BUILD_X11
#error Do not include on non-X11 builds
#endif
#include "utils/common.h"
#include <netwm.h>

View file

@ -15,6 +15,9 @@ ecm_qt_declare_logging_category(kwin_wayland_wrapper
Warning
)
target_link_libraries(kwin_wayland_wrapper Qt::Core Qt::DBus KF6::DBusAddons KF6::CoreAddons KWinXwaylandCommon)
target_link_libraries(kwin_wayland_wrapper Qt::Core Qt::DBus KF6::DBusAddons KF6::CoreAddons)
if (KWIN_BUILD_X11)
target_link_libraries(kwin_wayland_wrapper KWinXwaylandCommon)
endif()
set_property(TARGET kwin_wayland_wrapper PROPERTY C_STANDARD 11)
install(TARGETS kwin_wayland_wrapper ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})

View file

@ -20,6 +20,8 @@
* Usage kwin_wayland_wrapper [argForKwin] [argForKwin] ...
*/
#include "config-kwin.h"
#include <QCoreApplication>
#include <QDBusConnection>
#include <QDebug>
@ -33,8 +35,11 @@
#include "wl-socket.h"
#include "wrapper_logging.h"
#if KWIN_BUILD_X11
#include "xauthority.h"
#include "xwaylandsocket.h"
#endif
using namespace std::chrono_literals;
@ -55,10 +60,13 @@ private:
int m_crashCount = 0;
QProcess *m_kwinProcess = nullptr;
std::unique_ptr<KWin::XwaylandSocket> m_xwlSocket;
QTemporaryFile m_xauthorityFile;
const std::chrono::microseconds m_watchdogInterval;
bool m_watchdogIntervalOk;
#if KWIN_BUILD_X11
std::unique_ptr<KWin::XwaylandSocket> m_xwlSocket;
QTemporaryFile m_xauthorityFile;
#endif
};
KWinWrapper::KWinWrapper(QObject *parent)
@ -71,6 +79,7 @@ KWinWrapper::KWinWrapper(QObject *parent)
qFatal("Could not create wayland socket");
}
#if KWIN_BUILD_X11
if (qApp->arguments().contains(QLatin1String("--xwayland"))) {
m_xwlSocket = std::make_unique<KWin::XwaylandSocket>(KWin::XwaylandSocket::OperationMode::TransferFdsOnExec);
if (!m_xwlSocket->isValid()) {
@ -85,6 +94,7 @@ KWinWrapper::KWinWrapper(QObject *parent)
}
}
}
#endif
}
KWinWrapper::~KWinWrapper()
@ -102,6 +112,7 @@ void KWinWrapper::run()
args << "--wayland-fd" << QString::number(wl_socket_get_fd(m_socket));
args << "--socket" << QString::fromUtf8(wl_socket_get_display_name(m_socket));
#if KWIN_BUILD_X11
if (m_xwlSocket) {
const auto xwaylandFileDescriptors = m_xwlSocket->fileDescriptors();
for (const int &fileDescriptor : xwaylandFileDescriptors) {
@ -112,6 +123,7 @@ void KWinWrapper::run()
args << "--xwayland-xauthority" << m_xauthorityFile.fileName();
}
}
#endif
// attach our main process arguments
// the first entry is dropped as it will be our program name
@ -143,12 +155,14 @@ void KWinWrapper::run()
QProcessEnvironment env;
env.insert("WAYLAND_DISPLAY", QString::fromUtf8(wl_socket_get_display_name(m_socket)));
#if KWIN_BUILD_X11
if (m_xwlSocket) {
env.insert("DISPLAY", m_xwlSocket->name());
if (m_xauthorityFile.open()) {
env.insert("XAUTHORITY", m_xauthorityFile.fileName());
}
}
#endif
auto envSyncJob = new KUpdateLaunchEnvironmentJob(env);
connect(envSyncJob, &KUpdateLaunchEnvironmentJob::finished, this, []() {
// The service name is merely there to indicate to the world that we're up and ready with all envs exported

View file

@ -30,7 +30,9 @@
#include "tablet_input.h"
#include "touch_input.h"
#include "wayland/xdgtopleveldrag_v1.h"
#if KWIN_BUILD_X11
#include "x11window.h"
#endif
#if KWIN_BUILD_TABBOX
#include "tabbox/tabbox.h"
#endif
@ -2363,10 +2365,11 @@ static AbstractDropHandler *dropHandler(Window *window)
if (dropTarget) {
return dropTarget;
}
#if KWIN_BUILD_X11
if (qobject_cast<X11Window *>(window) && kwinApp()->xwayland()) {
return kwinApp()->xwayland()->xwlDropHandler();
}
#endif
return nullptr;
}

View file

@ -34,7 +34,6 @@
#include <KLocalizedString>
#include <KShell>
#include <KKeyServer>
#include <QDBusConnection>
#include <QDBusMessage>
@ -43,6 +42,7 @@
#include <QMenu>
#include <linux/input-event-codes.h>
#include <private/qxkbcommon_p.h>
#include <unistd.h>
#include <xkbcommon/xkbcommon-keysyms.h>
@ -60,13 +60,14 @@ static std::vector<quint32> textToKey(const QString &text)
return {};
}
const QList<int> syms(KKeyServer::keyQtToSymXs(sequence[0]));
QKeyEvent ev(QEvent::KeyPress, sequence[0], Qt::NoModifier);
const QList<xkb_keysym_t> syms(QXkbCommon::toKeysym(&ev));
if (syms.empty()) {
return {};
}
std::optional<int> keyCode;
for (int sym : syms) {
std::optional<xkb_keycode_t> keyCode;
for (xkb_keysym_t sym : syms) {
auto code = input()->keyboard()->xkb()->keycodeFromKeysym(sym);
if (code) {
keyCode = code;

View file

@ -20,11 +20,13 @@ kconfig_add_kcfg_files(kwinrules_SRCS ../../rulebooksettingsbase.kcfgc)
add_library(KWinRulesObjects STATIC ${kwinrules_SRCS})
set_property(TARGET KWinRulesObjects PROPERTY POSITION_INDEPENDENT_CODE ON)
set(kwin_kcm_rules_XCB_LIBS
XCB::CURSOR
XCB::XCB
XCB::XFIXES
)
if (KWIN_BUILD_X11)
set(kwin_kcm_rules_XCB_LIBS
XCB::CURSOR
XCB::XCB
XCB::XFIXES
)
endif()
set(kcm_libs
Qt::Quick

View file

@ -27,8 +27,12 @@ target_link_libraries(kcm_kwintabbox
KF6::Package
KF6::Service
KF6::XmlGui # For kkeysequencewidget
XCB::XCB
)
if (KWIN_BUILD_X11)
target_link_libraries(kcm_kwintabbox
XCB::XCB
)
endif()
########### install files ###############
install(FILES thumbnails/falkon.png

View file

@ -11,9 +11,11 @@
#include "wayland/seat.h"
#include "wayland/xdgforeign_v2.h"
#include "wayland_server.h"
#include "x11window.h"
#include "xdgactivationv1.h"
#include "xdgshellwindow.h"
#if KWIN_BUILD_X11
#include "x11window.h"
#endif
#include <QDir>
#include <QFileInfo>
@ -25,7 +27,11 @@ namespace KWin
KillPrompt::KillPrompt(Window *window)
: m_window(window)
{
#if KWIN_BUILD_X11
Q_ASSERT(qobject_cast<X11Window *>(window) || qobject_cast<XdgToplevelWindow *>(window));
#else
Q_ASSERT(qobject_cast<XdgToplevelWindow *>(window));
#endif
m_process.setProcessChannelMode(QProcess::ForwardedChannels);
@ -58,6 +64,7 @@ void KillPrompt::start(quint32 timestamp)
QString appId = !m_window->desktopFileName().isEmpty() ? m_window->desktopFileName() : m_window->resourceClass();
QString platform;
#if KWIN_BUILD_X11
if (auto *x11Window = qobject_cast<X11Window *>(m_window)) {
platform = QStringLiteral("xcb");
wid = QString::number(x11Window->window());
@ -65,7 +72,9 @@ void KillPrompt::start(quint32 timestamp)
if (!x11Window->clientMachine()->isLocal()) {
hostname = x11Window->clientMachine()->hostName();
}
} else if (auto *xdgToplevel = qobject_cast<XdgToplevelWindow *>(m_window)) {
} else
#endif
if (auto *xdgToplevel = qobject_cast<XdgToplevelWindow *>(m_window)) {
platform = QStringLiteral("wayland");
auto *exported = waylandServer()->exportAsForeign(xdgToplevel->surface());
wid = exported->handle();

View file

@ -67,9 +67,7 @@
#include "compositor.h"
#include "effect/effecthandler.h"
#include "focuschain.h"
#include "group.h"
#include "internalwindow.h"
#include "netinfo.h"
#include "rules.h"
#include "screenedge.h"
#include "tabbox/tabbox.h"
@ -77,7 +75,11 @@
#include "virtualdesktops.h"
#include "wayland_server.h"
#include "workspace.h"
#if KWIN_BUILD_X11
#include "group.h"
#include "netinfo.h"
#include "x11window.h"
#endif
#include <array>
@ -103,7 +105,9 @@ void Workspace::updateStackingOrder(bool propagate_new_windows)
force_restacking = false;
stacking_order = new_stacking_order;
if (changed || propagate_new_windows) {
#if KWIN_BUILD_X11
propagateWindows(propagate_new_windows);
#endif
for (int i = 0; i < stacking_order.size(); ++i) {
stacking_order[i]->setStackingOrder(i);
@ -117,6 +121,7 @@ void Workspace::updateStackingOrder(bool propagate_new_windows)
}
}
#if KWIN_BUILD_X11
/**
* Some fullscreen effects have to raise the screenedge on top of an input window, thus all windows
* this function puts them back where they belong for regular use and is some cheap variant of
@ -214,6 +219,7 @@ void Workspace::propagateWindows(bool propagate_new_windows)
}
rootInfo()->setClientListStacking(cl.constData(), cl.size());
}
#endif
/**
* Returns topmost visible window. Windows on the dock, the desktop
@ -306,6 +312,8 @@ void Workspace::lowerWindow(Window *window, bool nogroup)
unconstrained_stacking_order.removeAll(window);
unconstrained_stacking_order.prepend(window);
// TODO How X11-specific is this implementation?
#if KWIN_BUILD_X11
if (!nogroup && window->isTransient()) {
// lower also all windows in the group, in their reversed stacking order
QList<X11Window *> wins;
@ -318,6 +326,7 @@ void Workspace::lowerWindow(Window *window, bool nogroup)
}
}
}
#endif
}
void Workspace::lowerWindowWithinApplication(Window *window)
@ -416,6 +425,7 @@ void Workspace::raiseWindowRequest(Window *window, NET::RequestSource src, xcb_t
}
}
#if KWIN_BUILD_X11
void Workspace::lowerWindowRequest(X11Window *window, NET::RequestSource src, xcb_timestamp_t /*timestamp*/)
{
// If the window has support for all this focus stealing prevention stuff,
@ -428,6 +438,7 @@ void Workspace::lowerWindowRequest(X11Window *window, NET::RequestSource src, xc
lowerWindowWithinApplication(window);
}
}
#endif
void Workspace::lowerWindowRequest(Window *window)
{
@ -470,6 +481,7 @@ void Workspace::restackWindowUnderActive(Window *window)
restack(window, m_activeWindow);
}
#if KWIN_BUILD_X11
void Workspace::restoreSessionStackingOrder(X11Window *window)
{
if (window->sessionStackingOrder() < 0) {
@ -515,14 +527,16 @@ static Layer layerForWindow(const X11Window *window)
return layer;
}
#endif
static Layer computeLayer(const Window *window)
{
#if KWIN_BUILD_X11
if (auto x11Window = qobject_cast<const X11Window *>(window)) {
return layerForWindow(x11Window);
} else {
return window->layer();
}
#endif
return window->layer();
}
/**
@ -635,11 +649,13 @@ QList<T *> ensureStackingOrderInList(const QList<Window *> &stackingOrder, const
}
}
#if KWIN_BUILD_X11
// Ensure list is in stacking order
QList<X11Window *> Workspace::ensureStackingOrder(const QList<X11Window *> &list) const
{
return ensureStackingOrderInList(stacking_order, list);
}
#endif
QList<Window *> Workspace::ensureStackingOrder(const QList<Window *> &list) const
{
@ -651,6 +667,7 @@ QList<Window *> Workspace::unconstrainedStackingOrder() const
return unconstrained_stacking_order;
}
#if KWIN_BUILD_X11
void Workspace::updateXStackingOrder()
{
// we use our stacking order for managed windows, but X's for override-redirect windows
@ -672,100 +689,6 @@ void Workspace::updateXStackingOrder()
updateStackingOrder();
}
}
//*******************************
// Client
//*******************************
void X11Window::restackWindow(xcb_window_t above, int detail, NET::RequestSource src, xcb_timestamp_t timestamp, bool send_event)
{
X11Window *other = nullptr;
if (detail == XCB_STACK_MODE_OPPOSITE) {
other = workspace()->findClient(Predicate::WindowMatch, above);
if (!other) {
workspace()->raiseOrLowerWindow(this);
return;
}
auto it = workspace()->stackingOrder().constBegin(),
end = workspace()->stackingOrder().constEnd();
while (it != end) {
if (*it == this) {
detail = XCB_STACK_MODE_ABOVE;
break;
} else if (*it == other) {
detail = XCB_STACK_MODE_BELOW;
break;
}
++it;
}
} else if (detail == XCB_STACK_MODE_TOP_IF) {
other = workspace()->findClient(Predicate::WindowMatch, above);
if (other && other->frameGeometry().intersects(frameGeometry())) {
workspace()->raiseWindowRequest(this, src, timestamp);
}
return;
} else if (detail == XCB_STACK_MODE_BOTTOM_IF) {
other = workspace()->findClient(Predicate::WindowMatch, above);
if (other && other->frameGeometry().intersects(frameGeometry())) {
workspace()->lowerWindowRequest(this, src, timestamp);
}
return;
}
if (!other) {
other = workspace()->findClient(Predicate::WindowMatch, above);
}
if (other && detail == XCB_STACK_MODE_ABOVE) {
auto it = workspace()->stackingOrder().constEnd(),
begin = workspace()->stackingOrder().constBegin();
while (--it != begin) {
if (*it == other) { // the other one is top on stack
it = begin; // invalidate
src = NET::FromTool; // force
break;
}
X11Window *window = qobject_cast<X11Window *>(*it);
if (!window || !((*it)->isNormalWindow() && window->isShown() && (*it)->isOnCurrentDesktop() && (*it)->isOnCurrentActivity() && (*it)->isOnOutput(output()))) {
continue; // irrelevant windows
}
if (*(it - 1) == other) {
break; // "it" is the one above the target one, stack below "it"
}
}
if (it != begin && (*(it - 1) == other)) {
other = qobject_cast<X11Window *>(*it);
} else {
other = nullptr;
}
}
if (other) {
workspace()->restack(this, other);
} else if (detail == XCB_STACK_MODE_BELOW) {
workspace()->lowerWindowRequest(this, src, timestamp);
} else if (detail == XCB_STACK_MODE_ABOVE) {
workspace()->raiseWindowRequest(this, src, timestamp);
}
if (send_event) {
sendSyntheticConfigureNotify();
}
}
bool X11Window::belongsToDesktop() const
{
const auto members = group()->members();
for (const X11Window *window : members) {
if (window->isDesktop()) {
return true;
}
}
return false;
}
#endif
} // namespace

View file

@ -11,7 +11,9 @@
#include "config-kwin.h"
#if KWIN_BUILD_X11
#include "atoms.h"
#endif
#include "colors/colormanager.h"
#include "compositor.h"
#include "core/outputbackend.h"
@ -32,10 +34,13 @@
#include "screenedge.h"
#include "sm.h"
#include "tabletmodemanager.h"
#include "utils/xcbutils.h"
#include "wayland/surface.h"
#include "workspace.h"
#if KWIN_BUILD_X11
#include "utils/xcbutils.h"
#include "x11eventfilter.h"
#endif
#if KWIN_BUILD_SCREENLOCKER
#include "screenlockerwatcher.h"
@ -59,11 +64,13 @@
#endif
#include <unistd.h>
#if KWIN_BUILD_X11
// xcb
#include <xcb/damage.h>
#ifndef XCB_GE_GENERIC
#define XCB_GE_GENERIC 35
#endif
#endif
Q_DECLARE_METATYPE(KSharedConfigPtr)
@ -71,12 +78,16 @@ namespace KWin
{
Options *options;
#if KWIN_BUILD_X11
Atoms *atoms;
#endif
int Application::crashes = 0;
Application::Application(Application::OperationMode mode, int &argc, char **argv)
: QApplication(argc, argv)
#if KWIN_BUILD_X11
, m_eventFilter(new XcbEventFilter())
#endif
, m_configLock(false)
, m_config(KSharedConfig::openConfig(QStringLiteral("kwinrc")))
, m_kxkbConfig()
@ -150,8 +161,10 @@ void Application::notifyStarted()
void Application::destroyAtoms()
{
#if KWIN_BUILD_X11
delete atoms;
atoms = nullptr;
#endif
}
void Application::destroyPlatform()
@ -262,7 +275,9 @@ void Application::createInput()
void Application::createAtoms()
{
#if KWIN_BUILD_X11
atoms = new Atoms;
#endif
}
void Application::createOptions()
@ -295,6 +310,7 @@ TabletModeManager *Application::tabletModeManager() const
return m_tabletModeManager.get();
}
#if KWIN_BUILD_X11
void Application::installNativeX11EventFilter()
{
installNativeEventFilter(m_eventFilter.get());
@ -304,6 +320,7 @@ void Application::removeNativeX11EventFilter()
{
removeNativeEventFilter(m_eventFilter.get());
}
#endif
void Application::destroyInput()
{
@ -358,6 +375,7 @@ void Application::createEffectsHandler(Compositor *compositor, WorkspaceScene *s
new EffectsHandler(compositor, scene);
}
#if KWIN_BUILD_X11
void Application::registerEventFilter(X11EventFilter *filter)
{
if (filter->isGenericEvent()) {
@ -378,6 +396,7 @@ static X11EventFilterContainer *takeEventFilter(X11EventFilter *eventFilter,
}
return nullptr;
}
#endif
void Application::setXwaylandScale(qreal scale)
{
@ -403,12 +422,15 @@ void Application::applyXwaylandScale()
}
xwaylandGroup.sync();
#if KWIN_BUILD_X11
if (x11Connection()) {
// rerun the fonts kcm init that does the appropriate xrdb call with the new settings
QProcess::startDetached("kcminit", {"kcm_fonts_init", "kcm_style_init"});
}
#endif
}
#if KWIN_BUILD_X11
void Application::unregisterEventFilter(X11EventFilter *filter)
{
X11EventFilterContainer *container = nullptr;
@ -625,6 +647,8 @@ bool XcbEventFilter::nativeEventFilter(const QByteArray &eventType, void *messag
return false;
}
#endif
QProcessEnvironment Application::processStartupEnvironment() const
{
return m_processEnvironment;

View file

@ -21,7 +21,9 @@
#include <QApplication>
#include <QProcessEnvironment>
#if KWIN_BUILD_X11
#include <xcb/xcb.h>
#endif
class KPluginMetaData;
class QCommandLineParser;
@ -69,9 +71,11 @@ private:
class KWIN_EXPORT Application : public QApplication
{
Q_OBJECT
#if KWIN_BUILD_X11
Q_PROPERTY(quint32 x11Time READ x11Time WRITE setX11Time)
Q_PROPERTY(quint32 x11RootWindow READ x11RootWindow CONSTANT)
Q_PROPERTY(void *x11Connection READ x11Connection NOTIFY x11ConnectionChanged)
#endif
Q_PROPERTY(KSharedConfigPtr config READ config WRITE setConfig)
Q_PROPERTY(KSharedConfigPtr kxkbConfig READ kxkbConfig WRITE setKxkbConfig)
public:
@ -140,6 +144,7 @@ public:
void setupCommandLine(QCommandLineParser *parser);
void processCommandLine(QCommandLineParser *parser);
#if KWIN_BUILD_X11
void registerEventFilter(X11EventFilter *filter);
void unregisterEventFilter(X11EventFilter *filter);
bool dispatchEvent(xcb_generic_event_t *event);
@ -163,6 +168,7 @@ public:
*/
void updateXTime();
void updateX11Time(xcb_generic_event_t *event);
#endif
static void setCrashCount(int count);
static bool wasCrash();
@ -174,6 +180,7 @@ public:
*/
static void createAboutData();
#if KWIN_BUILD_X11
/**
* @returns the X11 root window.
*/
@ -197,7 +204,6 @@ public:
{
return m_connection;
}
/**
* Inheriting classes should use this method to set the X11 root window
* before accessing any X11 specific code pathes.
@ -218,6 +224,7 @@ public:
{
m_compositeWindow = window;
}
#endif
qreal xwaylandScale() const
{
@ -372,19 +379,23 @@ protected:
static int crashes;
private:
#if KWIN_BUILD_X11
QList<QPointer<X11EventFilterContainer>> m_eventFilters;
QList<QPointer<X11EventFilterContainer>> m_genericEventFilters;
std::unique_ptr<XcbEventFilter> m_eventFilter;
#endif
bool m_followLocale1 = false;
bool m_configLock;
KSharedConfigPtr m_config;
KSharedConfigPtr m_kxkbConfig;
KSharedConfigPtr m_inputConfig;
OperationMode m_operationMode;
#if KWIN_BUILD_X11
xcb_timestamp_t m_x11Time = XCB_TIME_CURRENT_TIME;
xcb_window_t m_rootWindow = XCB_WINDOW_NONE;
xcb_window_t m_compositeWindow = XCB_WINDOW_NONE;
xcb_connection_t *m_connection = nullptr;
#endif
#if KWIN_BUILD_ACTIVITIES
bool m_useKActivities = true;
#endif

View file

@ -25,8 +25,11 @@
#include "wayland/seat.h"
#include "wayland_server.h"
#include "workspace.h"
#if KWIN_BUILD_X11
#include "xwayland/xwayland.h"
#include "xwayland/xwaylandlauncher.h"
#endif
// KDE
#include <KCrash>
@ -121,7 +124,9 @@ ApplicationWayland::~ApplicationWayland()
if (effects) {
effects->unloadAllEffects();
}
#if KWIN_BUILD_X11
m_xwayland.reset();
#endif
destroyColorManager();
destroyWorkspace();
@ -132,10 +137,12 @@ ApplicationWayland::~ApplicationWayland()
void ApplicationWayland::performStartup()
{
#if KWIN_BUILD_X11
if (m_startXWayland) {
setOperationMode(OperationModeXwayland);
setXwaylandScale(config()->group(QStringLiteral("Xwayland")).readEntry("Scale", 1.0));
}
#endif
createOptions();
if (!outputBackend()->initialize()) {
@ -162,6 +169,7 @@ void ApplicationWayland::continueStartupWithScene()
qFatal("Failed to initialze the Wayland server, exiting now");
}
#if KWIN_BUILD_X11
if (operationMode() == OperationModeXwayland) {
m_xwayland = std::make_unique<Xwl::Xwayland>(this);
m_xwayland->xwaylandLauncher()->setListenFDs(m_xwaylandListenFds);
@ -170,6 +178,7 @@ void ApplicationWayland::continueStartupWithScene()
m_xwayland->init();
connect(m_xwayland.get(), &Xwl::Xwayland::started, this, &ApplicationWayland::applyXwaylandScale);
}
#endif
startSession();
notifyStarted();
}
@ -247,10 +256,12 @@ void ApplicationWayland::startSession()
}
}
#if KWIN_BUILD_X11
XwaylandInterface *ApplicationWayland::xwayland() const
{
return m_xwayland.get();
}
#endif
} // namespace
@ -287,14 +298,18 @@ int main(int argc, char *argv[])
KWin::Application::createAboutData();
#if KWIN_BUILD_X11
QCommandLineOption xwaylandOption(QStringLiteral("xwayland"),
i18n("Start a rootless Xwayland server."));
#endif
QCommandLineOption waylandSocketOption(QStringList{QStringLiteral("s"), QStringLiteral("socket")},
i18n("Name of the Wayland socket to listen on. If not set \"wayland-0\" is used."),
QStringLiteral("socket"));
#if KWIN_BUILD_X11
QCommandLineOption x11DisplayOption(QStringLiteral("x11-display"),
i18n("The X11 Display to use in windowed mode on platform X11."),
QStringLiteral("display"));
#endif
QCommandLineOption waylandDisplayOption(QStringLiteral("wayland-display"),
i18n("The Wayland Display to use in windowed mode on platform Wayland."),
QStringLiteral("display"));
@ -342,14 +357,18 @@ int main(int argc, char *argv[])
QCommandLineParser parser;
a.setupCommandLine(&parser);
#if KWIN_BUILD_X11
parser.addOption(xwaylandOption);
#endif
parser.addOption(waylandSocketOption);
parser.addOption(waylandSocketFdOption);
parser.addOption(xwaylandListenFdOption);
parser.addOption(xwaylandDisplayOption);
parser.addOption(xwaylandXAuthorityOption);
parser.addOption(replaceOption);
#if KWIN_BUILD_X11
parser.addOption(x11DisplayOption);
#endif
parser.addOption(waylandDisplayOption);
parser.addOption(virtualFbOption);
parser.addOption(widthOption);
@ -429,8 +448,10 @@ int main(int argc, char *argv[])
// Decide what backend to use.
if (parser.isSet(drmOption)) {
backendType = BackendType::Kms;
#if KWIN_BUILD_X11
} else if (parser.isSet(x11DisplayOption)) {
backendType = BackendType::X11;
#endif
} else if (parser.isSet(waylandDisplayOption)) {
backendType = BackendType::Wayland;
} else if (parser.isSet(virtualFbOption)) {
@ -539,6 +560,7 @@ int main(int argc, char *argv[])
a.setOutputBackend(std::move(outputBackend));
break;
}
#if KWIN_BUILD_X11
case BackendType::X11: {
QString display = parser.value(x11DisplayOption);
if (display.isEmpty()) {
@ -553,6 +575,7 @@ int main(int argc, char *argv[])
}));
break;
}
#endif
case BackendType::Wayland: {
QString socketName = parser.value(waylandDisplayOption);
if (socketName.isEmpty()) {
@ -576,6 +599,7 @@ int main(int argc, char *argv[])
}
a.setProcessStartupEnvironment(environment);
#if KWIN_BUILD_X11
if (parser.isSet(xwaylandOption)) {
a.setStartXwayland(true);
@ -601,6 +625,7 @@ int main(int argc, char *argv[])
}
}
}
#endif
a.setApplicationsToStart(parser.positionalArguments());
a.setInputMethodServerToStart(parser.value(inputMethodOption));

View file

@ -25,6 +25,7 @@ public:
ApplicationWayland(int &argc, char **argv);
~ApplicationWayland() override;
#if KWIN_BUILD_X11
void setStartXwayland(bool start)
{
m_startXWayland = start;
@ -41,6 +42,8 @@ public:
{
m_xwaylandXauthority = xauthority;
}
XwaylandInterface *xwayland() const override;
#endif
void setApplicationsToStart(const QStringList &applications)
{
m_applicationsToStart = applications;
@ -54,8 +57,6 @@ public:
m_sessionArgument = session;
}
XwaylandInterface *xwayland() const override;
protected:
void performStartup() override;
@ -64,15 +65,17 @@ private:
void startSession();
void refreshSettings(const KConfigGroup &group, const QByteArrayList &names);
bool m_startXWayland = false;
QStringList m_applicationsToStart;
QString m_inputMethodServerToStart;
QString m_sessionArgument;
#if KWIN_BUILD_X11
bool m_startXWayland = false;
std::unique_ptr<Xwl::Xwayland> m_xwayland;
QList<int> m_xwaylandListenFds;
QString m_xwaylandDisplay;
QString m_xwaylandXauthority;
#endif
KConfigWatcher::Ptr m_settingsWatcher;
};

View file

@ -11,6 +11,12 @@
*/
#pragma once
#include "config-kwin.h"
#if !KWIN_BUILD_X11
#error Do not include on non-X11 builds
#endif
#include <NETWM>
#include <memory>

View file

@ -10,10 +10,13 @@
#include "opengl/glplatform.h"
// include kwinglutils_funcs.h to avoid the redeclaration issues
// between qopengl.h and epoxy/gl.h
#include "effect/xcb.h"
#include "opengl/glutils_funcs.h"
#include <epoxy/gl.h>
#if KWIN_BUILD_X11
#include "effect/xcb.h"
#endif
#include <QDebug>
#include <QOpenGLContext>
#include <QRegularExpression>

View file

@ -18,9 +18,12 @@
#include "rules.h"
#include "virtualdesktops.h"
#include "workspace.h"
#if KWIN_BUILD_X11
#include "x11window.h"
#endif
#endif
#include "window.h"
#include <QTextStream>
#include <QTimer>

View file

@ -13,11 +13,14 @@
#include "core/rendertarget.h"
#include "core/renderviewport.h"
#include "effect/effecthandler.h"
#include "utils/xcbutils.h"
#include "wayland/contrast.h"
#include "wayland/display.h"
#include "wayland/surface.h"
#if KWIN_BUILD_X11
#include "utils/xcbutils.h"
#endif
#include <QCoreApplication>
#include <QMatrix4x4>
#include <QTimer>
@ -40,9 +43,11 @@ ContrastEffect::ContrastEffect()
// ### Hackish way to announce support.
// Should be included in _NET_SUPPORTED instead.
if (m_shader && m_shader->isValid()) {
#if KWIN_BUILD_X11
if (effects->xcbConnection()) {
m_net_wm_contrast_region = effects->announceSupportProperty(s_contrastAtomName, this);
}
#endif
if (effects->waylandDisplay()) {
if (!s_contrastManagerRemoveTimer) {
s_contrastManagerRemoveTimer = new QTimer(QCoreApplication::instance());
@ -61,13 +66,16 @@ ContrastEffect::ContrastEffect()
connect(effects, &EffectsHandler::windowAdded, this, &ContrastEffect::slotWindowAdded);
connect(effects, &EffectsHandler::windowDeleted, this, &ContrastEffect::slotWindowDeleted);
connect(effects, &EffectsHandler::propertyNotify, this, &ContrastEffect::slotPropertyNotify);
connect(effects, &EffectsHandler::virtualScreenGeometryChanged, this, &ContrastEffect::slotScreenGeometryChanged);
#if KWIN_BUILD_X11
connect(effects, &EffectsHandler::propertyNotify, this, &ContrastEffect::slotPropertyNotify);
connect(effects, &EffectsHandler::xcbConnectionChanged, this, [this]() {
if (m_shader && m_shader->isValid()) {
m_net_wm_contrast_region = effects->announceSupportProperty(s_contrastAtomName, this);
}
});
#endif
// Fetch the contrast regions for all windows
const QList<EffectWindow *> windowList = effects->stackingOrder();
@ -102,10 +110,11 @@ void ContrastEffect::updateContrastRegion(EffectWindow *w)
{
QRegion region;
QMatrix4x4 matrix;
float colorTransform[16];
bool valid = false;
#if KWIN_BUILD_X11
if (m_net_wm_contrast_region != XCB_ATOM_NONE) {
float colorTransform[16];
const QByteArray value = w->readProperty(m_net_wm_contrast_region, m_net_wm_contrast_region, 32);
if (value.size() > 0 && !((value.size() - (16 * sizeof(uint32_t))) % ((4 * sizeof(uint32_t))))) {
@ -129,6 +138,7 @@ void ContrastEffect::updateContrastRegion(EffectWindow *w)
valid = !value.isNull();
}
#endif
SurfaceInterface *surf = w->surface();
@ -217,12 +227,14 @@ void ContrastEffect::slotWindowDeleted(EffectWindow *w)
}
}
#if KWIN_BUILD_X11
void ContrastEffect::slotPropertyNotify(EffectWindow *w, long atom)
{
if (w && atom == m_net_wm_contrast_region && m_net_wm_contrast_region != XCB_ATOM_NONE) {
updateContrastRegion(w);
}
}
#endif
QMatrix4x4 ContrastEffect::colorMatrix(qreal contrast, qreal intensity, qreal saturation)
{

View file

@ -49,7 +49,9 @@ public:
public Q_SLOTS:
void slotWindowAdded(KWin::EffectWindow *w);
void slotWindowDeleted(KWin::EffectWindow *w);
#if KWIN_BUILD_X11
void slotPropertyNotify(KWin::EffectWindow *w, long atom);
#endif
void slotScreenGeometryChanged();
private:
@ -62,7 +64,10 @@ private:
private:
std::unique_ptr<ContrastShader> m_shader;
#if KWIN_BUILD_X11
long m_net_wm_contrast_region = 0;
#endif
QHash<const EffectWindow *, QMetaObject::Connection> m_contrastChangedConnections; // used only in Wayland to keep track of effect changed
struct Data
{

View file

@ -15,11 +15,14 @@
#include "core/renderviewport.h"
#include "effect/effecthandler.h"
#include "opengl/glplatform.h"
#include "utils/xcbutils.h"
#include "wayland/blur.h"
#include "wayland/display.h"
#include "wayland/surface.h"
#if KWIN_BUILD_X11
#include "utils/xcbutils.h"
#endif
#include <QGuiApplication>
#include <QMatrix4x4>
#include <QScreen>
@ -94,9 +97,11 @@ BlurEffect::BlurEffect()
initBlurStrengthValues();
reconfigure(ReconfigureAll);
#if KWIN_BUILD_X11
if (effects->xcbConnection()) {
net_wm_blur_region = effects->announceSupportProperty(s_blurAtomName, this);
}
#endif
if (effects->waylandDisplay()) {
if (!s_blurManagerRemoveTimer) {
@ -116,10 +121,12 @@ BlurEffect::BlurEffect()
connect(effects, &EffectsHandler::windowAdded, this, &BlurEffect::slotWindowAdded);
connect(effects, &EffectsHandler::windowDeleted, this, &BlurEffect::slotWindowDeleted);
connect(effects, &EffectsHandler::screenRemoved, this, &BlurEffect::slotScreenRemoved);
#if KWIN_BUILD_X11
connect(effects, &EffectsHandler::propertyNotify, this, &BlurEffect::slotPropertyNotify);
connect(effects, &EffectsHandler::xcbConnectionChanged, this, [this]() {
net_wm_blur_region = effects->announceSupportProperty(s_blurAtomName, this);
});
#endif
// Fetch the blur regions for all windows
const auto stackingOrder = effects->stackingOrder();
@ -215,6 +222,7 @@ void BlurEffect::updateBlurRegion(EffectWindow *w)
std::optional<QRegion> content;
std::optional<QRegion> frame;
#if KWIN_BUILD_X11
if (net_wm_blur_region != XCB_ATOM_NONE) {
const QByteArray value = w->readProperty(net_wm_blur_region, XCB_ATOM_CARDINAL, 32);
QRegion region;
@ -232,6 +240,7 @@ void BlurEffect::updateBlurRegion(EffectWindow *w)
content = region;
}
}
#endif
SurfaceInterface *surf = w->surface();
@ -305,12 +314,14 @@ void BlurEffect::slotScreenRemoved(KWin::Output *screen)
}
}
#if KWIN_BUILD_X11
void BlurEffect::slotPropertyNotify(EffectWindow *w, long atom)
{
if (w && atom == net_wm_blur_region && net_wm_blur_region != XCB_ATOM_NONE) {
updateBlurRegion(w);
}
}
#endif
void BlurEffect::setupDecorationConnections(EffectWindow *w)
{

View file

@ -71,7 +71,9 @@ public Q_SLOTS:
void slotWindowAdded(KWin::EffectWindow *w);
void slotWindowDeleted(KWin::EffectWindow *w);
void slotScreenRemoved(KWin::Output *screen);
#if KWIN_BUILD_X11
void slotPropertyNotify(KWin::EffectWindow *w, long atom);
#endif
void setupDecorationConnections(EffectWindow *w);
private:
@ -114,7 +116,9 @@ private:
} m_noisePass;
bool m_valid = false;
#if KWIN_BUILD_X11
long net_wm_blur_region = 0;
#endif
QRegion m_paintedArea; // keeps track of all painted areas (from bottom to top)
QRegion m_currentBlur; // keeps track of the currently blured area of the windows(from bottom to top)
Output *m_currentScreen = nullptr;

View file

@ -14,4 +14,4 @@ target_sources(buttonsrebind PRIVATE
main.cpp
buttonrebindsfilter.cpp
)
target_link_libraries(buttonsrebind PRIVATE kwin KF6::WindowSystem XKB::XKB)
target_link_libraries(buttonsrebind PRIVATE kwin Qt::GuiPrivate XKB::XKB)

View file

@ -13,8 +13,6 @@
#include "keyboard_input.h"
#include "xkb.h"
#include <KKeyServer>
#include <QMetaEnum>
#include <linux/input-event-codes.h>
@ -23,6 +21,8 @@
#include <optional>
#include <utility>
#include <private/qxkbcommon_p.h>
// Tells us that we are already in a binding event
class RebindScope
{
@ -300,7 +300,8 @@ bool ButtonRebindsFilter::sendKeySequence(const QKeySequence &keys, bool pressed
}
}
const QList<int> syms(KKeyServer::keyQtToSymXs(keys[0]));
QKeyEvent ev(QEvent::KeyPress, keys[0], Qt::NoModifier);
const QList<xkb_keysym_t> syms(QXkbCommon::toKeysym(&ev));
if (syms.empty()) {
qCWarning(KWIN_BUTTONREBINDS) << "Could not convert" << keys << "to keysym";
return false;

View file

@ -23,17 +23,19 @@ HighlightWindowEffect::HighlightWindowEffect()
, m_fadeDuration(animationTime(150))
, m_monitorWindow(nullptr)
{
#if KWIN_BUILD_X11
// TODO KF6 remove atom support
m_atom = effects->announceSupportProperty("_KDE_WINDOW_HIGHLIGHT", this);
connect(effects, &EffectsHandler::windowAdded, this, &HighlightWindowEffect::slotWindowAdded);
connect(effects, &EffectsHandler::windowClosed, this, &HighlightWindowEffect::slotWindowClosed);
connect(effects, &EffectsHandler::windowDeleted, this, &HighlightWindowEffect::slotWindowDeleted);
connect(effects, &EffectsHandler::propertyNotify, this, [this](EffectWindow *w, long atom) {
slotPropertyNotify(w, atom, nullptr);
});
connect(effects, &EffectsHandler::xcbConnectionChanged, this, [this]() {
m_atom = effects->announceSupportProperty("_KDE_WINDOW_HIGHLIGHT", this);
});
connect(effects, &EffectsHandler::propertyNotify, this, [this](EffectWindow *w, long atom) {
slotPropertyNotify(w, atom, nullptr);
});
#endif
connect(effects, &EffectsHandler::windowAdded, this, &HighlightWindowEffect::slotWindowAdded);
connect(effects, &EffectsHandler::windowClosed, this, &HighlightWindowEffect::slotWindowClosed);
connect(effects, &EffectsHandler::windowDeleted, this, &HighlightWindowEffect::slotWindowDeleted);
QDBusConnection::sessionBus().registerObject(QStringLiteral("/org/kde/KWin/HighlightWindow"),
QStringLiteral("org.kde.KWin.HighlightWindow"),
@ -93,7 +95,9 @@ void HighlightWindowEffect::slotWindowAdded(EffectWindow *w)
complete(animationId);
}
}
#if KWIN_BUILD_X11
slotPropertyNotify(w, m_atom, w); // Check initial value
#endif
}
void HighlightWindowEffect::slotWindowClosed(EffectWindow *w)
@ -108,6 +112,7 @@ void HighlightWindowEffect::slotWindowDeleted(EffectWindow *w)
m_animations.remove(w);
}
#if KWIN_BUILD_X11
void HighlightWindowEffect::slotPropertyNotify(EffectWindow *w, long a, EffectWindow *addedWindow)
{
if (a != m_atom || m_atom == XCB_ATOM_NONE) {
@ -156,6 +161,7 @@ void HighlightWindowEffect::slotPropertyNotify(EffectWindow *w, long a, EffectWi
}
prepareHighlighting();
}
#endif
void HighlightWindowEffect::prepareHighlighting()
{

View file

@ -9,6 +9,8 @@
#pragma once
#include "config-kwin.h"
#include "effect/animationeffect.h"
namespace KWin
@ -35,7 +37,9 @@ public Q_SLOTS:
void slotWindowAdded(KWin::EffectWindow *w);
void slotWindowClosed(KWin::EffectWindow *w);
void slotWindowDeleted(KWin::EffectWindow *w);
#if KWIN_BUILD_X11
void slotPropertyNotify(KWin::EffectWindow *w, long atom, EffectWindow *addedWindow = nullptr);
#endif
private:
quint64 startGhostAnimation(EffectWindow *window);
@ -48,7 +52,9 @@ private:
void finishHighlighting();
void highlightWindows(const QList<KWin::EffectWindow *> &windows);
#if KWIN_BUILD_X11
long m_atom;
#endif
QList<EffectWindow *> m_highlightedWindows;
QHash<EffectWindow *, quint64> m_animations;
QEasingCurve m_easingCurve;

View file

@ -46,15 +46,19 @@ namespace KWin
KscreenEffect::KscreenEffect()
: Effect()
#if KWIN_BUILD_X11
, m_atom(effects->waylandDisplay() ? XCB_ATOM_NONE : effects->announceSupportProperty("_KDE_KWIN_KSCREEN_SUPPORT", this))
#endif
{
KscreenConfig::instance(effects->config());
#if KWIN_BUILD_X11
if (!effects->waylandDisplay()) {
connect(effects, &EffectsHandler::propertyNotify, this, &KscreenEffect::propertyNotify);
connect(effects, &EffectsHandler::xcbConnectionChanged, this, [this]() {
m_atom = effects->announceSupportProperty(QByteArrayLiteral("_KDE_KWIN_KSCREEN_SUPPORT"), this);
});
}
#endif
reconfigure(ReconfigureAll);
const QList<Output *> screens = effects->screens();
@ -173,6 +177,7 @@ void KscreenEffect::setState(ScreenState &state, FadeOutState newState)
effects->addRepaintFull();
}
#if KWIN_BUILD_X11
void KscreenEffect::propertyNotify(EffectWindow *window, long int atom)
{
if (window || atom != m_atom || m_atom == XCB_ATOM_NONE) {
@ -191,6 +196,7 @@ void KscreenEffect::propertyNotify(EffectWindow *window, long int atom)
setState(m_xcbState, FadeOutState(data[0]));
}
#endif
void KscreenEffect::switchState(ScreenState &state)
{
@ -202,19 +208,29 @@ void KscreenEffect::switchState(ScreenState &state)
state.m_state = StateNormal;
value = 0l;
}
#if KWIN_BUILD_X11
if (value != -1l && m_atom != XCB_ATOM_NONE) {
xcb_change_property(effects->xcbConnection(), XCB_PROP_MODE_REPLACE, effects->x11RootWindow(), m_atom, XCB_ATOM_CARDINAL, 32, 1, &value);
}
#endif
}
bool KscreenEffect::isActive() const
{
return !m_waylandStates.isEmpty() || (!effects->waylandDisplay() && m_atom && m_xcbState.m_state != StateNormal);
return !m_waylandStates.isEmpty()
#if KWIN_BUILD_X11
|| (!effects->waylandDisplay() && m_atom && m_xcbState.m_state != StateNormal)
#endif
;
}
bool KscreenEffect::isScreenActive(Output *screen) const
{
return m_waylandStates.contains(screen) || (!effects->waylandDisplay() && m_atom && m_xcbState.m_state != StateNormal);
return m_waylandStates.contains(screen)
#if KWIN_BUILD_X11
|| (!effects->waylandDisplay() && m_atom && m_xcbState.m_state != StateNormal)
#endif
;
}
} // namespace KWin

View file

@ -37,8 +37,10 @@ public:
return 99;
}
#if KWIN_BUILD_X11
private Q_SLOTS:
void propertyNotify(KWin::EffectWindow *window, long atom);
#endif
private:
enum FadeOutState {
@ -62,7 +64,9 @@ private:
QHash<Output *, ScreenState> m_waylandStates;
ScreenState m_xcbState;
Output *m_currentScreen = nullptr;
#if KWIN_BUILD_X11
xcb_atom_t m_atom;
#endif
};
} // namespace KWin

View file

@ -53,14 +53,16 @@ SlidingPopupsEffect::SlidingPopupsEffect()
m_slideLength = QFontMetrics(QGuiApplication::font()).height() * 8;
#if KWIN_BUILD_X11
m_atom = effects->announceSupportProperty("_KDE_SLIDE", this);
connect(effects, &EffectsHandler::windowAdded, this, &SlidingPopupsEffect::slotWindowAdded);
connect(effects, &EffectsHandler::windowClosed, this, &SlidingPopupsEffect::slotWindowClosed);
connect(effects, &EffectsHandler::windowDeleted, this, &SlidingPopupsEffect::slotWindowDeleted);
connect(effects, &EffectsHandler::propertyNotify, this, &SlidingPopupsEffect::slotPropertyNotify);
connect(effects, &EffectsHandler::xcbConnectionChanged, this, [this]() {
m_atom = effects->announceSupportProperty(QByteArrayLiteral("_KDE_SLIDE"), this);
});
connect(effects, &EffectsHandler::propertyNotify, this, &SlidingPopupsEffect::slotPropertyNotify);
#endif
connect(effects, &EffectsHandler::windowAdded, this, &SlidingPopupsEffect::slotWindowAdded);
connect(effects, &EffectsHandler::windowClosed, this, &SlidingPopupsEffect::slotWindowClosed);
connect(effects, &EffectsHandler::windowDeleted, this, &SlidingPopupsEffect::slotWindowDeleted);
connect(effects, &EffectsHandler::desktopChanged,
this, &SlidingPopupsEffect::stopAnimations);
connect(effects, &EffectsHandler::activeFullScreenEffectChanged,
@ -209,10 +211,12 @@ void SlidingPopupsEffect::setupSlideData(EffectWindow *w)
connect(w, &EffectWindow::windowFrameGeometryChanged, this, &SlidingPopupsEffect::slotWindowFrameGeometryChanged);
connect(w, &EffectWindow::windowHiddenChanged, this, &SlidingPopupsEffect::slotWindowHiddenChanged);
#if KWIN_BUILD_X11
// X11
if (m_atom != XCB_ATOM_NONE) {
slotPropertyNotify(w, m_atom);
}
#endif
// Wayland
if (auto surf = w->surface()) {
@ -257,6 +261,7 @@ void SlidingPopupsEffect::slotWindowHiddenChanged(EffectWindow *w)
}
}
#if KWIN_BUILD_X11
void SlidingPopupsEffect::slotPropertyNotify(EffectWindow *w, long atom)
{
if (!w || atom != m_atom || m_atom == XCB_ATOM_NONE) {
@ -333,6 +338,7 @@ void SlidingPopupsEffect::slotPropertyNotify(EffectWindow *w, long atom)
setupAnimData(w);
}
#endif
void SlidingPopupsEffect::slotWindowFrameGeometryChanged(EffectWindow *w, const QRectF &)
{

View file

@ -11,6 +11,8 @@
#pragma once
// Include with base class for effects.
#include "config-kwin.h"
#include "effect/effect.h"
#include "effect/effectwindow.h"
#include "effect/timeline.h"
@ -52,7 +54,9 @@ private Q_SLOTS:
void slotWindowAdded(EffectWindow *w);
void slotWindowClosed(EffectWindow *w);
void slotWindowDeleted(EffectWindow *w);
#if KWIN_BUILD_X11
void slotPropertyNotify(EffectWindow *w, long atom);
#endif
void slotWaylandSlideOnShowChanged(EffectWindow *w);
void slotWindowFrameGeometryChanged(EffectWindow *w, const QRectF &);
void slotWindowHiddenChanged(EffectWindow *w);
@ -69,7 +73,9 @@ private:
static SlideManagerInterface *s_slideManager;
static QTimer *s_slideManagerRemoveTimer;
#if KWIN_BUILD_X11
long m_atom = 0;
#endif
int m_slideLength;
std::chrono::milliseconds m_slideInDuration;

View file

@ -20,7 +20,9 @@
#include <QTimer>
// KDE
#include <KConfigGroup>
#if KWIN_BUILD_X11
#include <KSelectionOwner>
#endif
#include <KSharedConfig>
#include <KWindowSystem>
// KWin
@ -72,8 +74,10 @@ static const int s_startupDefaultTimeout = 5;
StartupFeedbackEffect::StartupFeedbackEffect()
: m_bounceSizesRatio(1.0)
#if KWIN_BUILD_X11
, m_startupInfo(new KStartupInfo(KStartupInfo::CleanOnCantDetect, this))
, m_selection(nullptr)
#endif
, m_active(false)
, m_frame(0)
, m_progress(0)
@ -83,6 +87,7 @@ StartupFeedbackEffect::StartupFeedbackEffect()
, m_configWatcher(KConfigWatcher::create(KSharedConfig::openConfig("klaunchrc", KConfig::NoGlobals)))
, m_splashVisible(false)
{
#if KWIN_BUILD_X11
// TODO: move somewhere that is x11-specific
if (KWindowSystem::isPlatformX11()) {
m_selection = new KSelectionOwner("_KDE_STARTUP_FEEDBACK", effects->xcbConnection(), effects->x11RootWindow(), this);
@ -99,6 +104,7 @@ StartupFeedbackEffect::StartupFeedbackEffect()
const auto icon = QIcon::fromTheme(data.findIcon(), QIcon::fromTheme(QStringLiteral("system-run")));
Q_EMIT effects->startupChanged(id.id(), icon);
});
#endif
connect(effects, &EffectsHandler::startupAdded, this, &StartupFeedbackEffect::gotNewStartup);
connect(effects, &EffectsHandler::startupRemoved, this, &StartupFeedbackEffect::gotRemoveStartup);
@ -141,7 +147,9 @@ void StartupFeedbackEffect::reconfigure(Effect::ReconfigureFlags flags)
c = m_configWatcher->config()->group(QStringLiteral("BusyCursorSettings"));
m_timeout = std::chrono::seconds(c.readEntry("Timeout", s_startupDefaultTimeout));
#if KWIN_BUILD_X11
m_startupInfo->setTimeout(m_timeout.count());
#endif
const bool busyBlinking = c.readEntry("Blinking", false);
const bool busyBouncing = c.readEntry("Bouncing", true);
if (!busyCursor) {

View file

@ -10,7 +10,11 @@
#pragma once
#include "effect/effect.h"
#include <KConfigWatcher>
#if KWIN_BUILD_X11
#include <KStartupInfo>
#endif
#include <QIcon>
#include <QObject>
#include <chrono>
@ -77,8 +81,10 @@ private:
QSize feedbackIconSize() const;
qreal m_bounceSizesRatio;
#if KWIN_BUILD_X11
KStartupInfo *m_startupInfo;
KSelectionOwner *m_selection;
#endif
QString m_currentStartup;
QMap<QString, Startup> m_startups;
bool m_active;

View file

@ -27,14 +27,17 @@
#include "wayland/seat.h"
#include "wayland/surface.h"
#include "wayland_server.h"
#include "window.h"
#include "workspace.h"
#include "x11window.h"
// KDecoration
#include <KDecoration2/Decoration>
// screenlocker
#if KWIN_BUILD_SCREENLOCKER
#include <KScreenLocker/KsldApp>
#endif
#if KWIN_BUILD_X11
#include "x11window.h"
#endif
#include <KLocalizedString>

View file

@ -7,6 +7,11 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "config-kwin.h"
#if !KWIN_BUILD_X11
#error Do not include on non-X11 builds
#endif
#include "x11eventfilter.h"

View file

@ -11,7 +11,10 @@
#include "wayland/subcompositor.h"
#include "wayland/surface.h"
#include "window.h"
#if KWIN_BUILD_X11
#include "x11window.h"
#endif
namespace KWin
{
@ -208,6 +211,7 @@ bool SurfacePixmapWayland::isValid() const
return m_bufferRef;
}
#if KWIN_BUILD_X11
SurfaceItemXwayland::SurfaceItemXwayland(X11Window *window, Scene *scene, Item *parent)
: SurfaceItemWayland(window->surface(), scene, parent)
, m_window(window)
@ -237,6 +241,7 @@ QRegion SurfaceItemXwayland::opaque() const
}
return QRegion();
}
#endif
} // namespace KWin

View file

@ -74,6 +74,7 @@ private:
SurfaceItemWayland *m_item;
};
#if KWIN_BUILD_X11
/**
* The SurfaceItemXwayland class represents an Xwayland surface in the scene.
*/
@ -90,5 +91,6 @@ public:
private:
X11Window *m_window;
};
#endif
} // namespace KWin

View file

@ -16,7 +16,9 @@
#include "wayland_server.h"
#include "window.h"
#include "workspace.h"
#if KWIN_BUILD_X11
#include "x11window.h"
#endif
#include <KDecoration2/Decoration>
@ -300,6 +302,7 @@ void WindowItem::freeze()
}
}
#if KWIN_BUILD_X11
WindowItemX11::WindowItemX11(X11Window *window, Scene *scene, Item *parent)
: WindowItem(window, scene, parent)
{
@ -326,6 +329,7 @@ void WindowItemX11::initialize()
Q_UNREACHABLE();
}
}
#endif
WindowItemWayland::WindowItemWayland(Window *window, Scene *scene, Item *parent)
: WindowItem(window, scene, parent)

View file

@ -6,6 +6,8 @@
#pragma once
#include "config-kwin.h"
#include "scene/item.h"
namespace KDecoration2
@ -88,6 +90,7 @@ private:
int m_forceVisibleByActivityCount = 0;
};
#if KWIN_BUILD_X11
/**
* The WindowItemX11 class represents an X11 window (both on X11 and Wayland sessions).
*
@ -104,6 +107,7 @@ public:
private Q_SLOTS:
void initialize();
};
#endif
/**
* The WindowItemWayland class represents a Wayland window.

View file

@ -61,6 +61,7 @@
#include "core/renderviewport.h"
#include "effect/effecthandler.h"
#include "internalwindow.h"
#include "scene/decorationitem.h"
#include "scene/dndiconitem.h"
#include "scene/itemrenderer.h"
#include "scene/shadowitem.h"
@ -71,8 +72,11 @@
#include "wayland/surface.h"
#include "wayland_server.h"
#include "waylandwindow.h"
#include "window.h"
#include "workspace.h"
#if KWIN_BUILD_X11
#include "x11window.h"
#endif
#include <QtMath>

View file

@ -30,8 +30,11 @@
#include "virtualdesktops.h"
#include "wayland/seat.h"
#include "wayland_server.h"
#include <window.h>
#include <workspace.h>
#include <x11window.h>
#if KWIN_BUILD_X11
#include "x11window.h"
#endif
// DBus generated
#if KWIN_BUILD_SCREENLOCKER
#include "screenlocker_interface.h"
@ -49,6 +52,7 @@
#include <QTextStream>
#include <QTimer>
#include <QWidget>
#include <span>
namespace KWin
{
@ -1463,6 +1467,7 @@ bool ScreenEdges::isEntered(QMouseEvent *event)
return activated;
}
#if KWIN_BUILD_X11
bool ScreenEdges::handleEnterNotifiy(xcb_window_t window, const QPoint &point, const QDateTime &timestamp)
{
bool activated = false;
@ -1501,7 +1506,16 @@ bool ScreenEdges::handleEnterNotifiy(xcb_window_t window, const QPoint &point, c
}
return activated;
}
#endif
void ScreenEdges::ensureOnTop()
{
#if KWIN_BUILD_X11
Xcb::restackWindowsWithRaise(windows());
#endif
}
#if KWIN_BUILD_X11
bool ScreenEdges::handleDndNotify(xcb_window_t window, const QPoint &point)
{
for (const auto &edge : m_edges) {
@ -1517,11 +1531,6 @@ bool ScreenEdges::handleDndNotify(xcb_window_t window, const QPoint &point)
return false;
}
void ScreenEdges::ensureOnTop()
{
Xcb::restackWindowsWithRaise(windows());
}
QList<xcb_window_t> ScreenEdges::windows() const
{
QList<xcb_window_t> wins;
@ -1538,6 +1547,7 @@ QList<xcb_window_t> ScreenEdges::windows() const
}
return wins;
}
#endif
void ScreenEdges::setRemainActiveOnFullscreen(bool remainActive)
{

View file

@ -331,11 +331,13 @@ public:
void ensureOnTop();
bool isEntered(QMouseEvent *event);
#if KWIN_BUILD_X11
/**
* Returns a QList of all existing screen edge windows
* @return all existing screen edge windows in a QList
*/
QList<xcb_window_t> windows() const;
#endif
bool isDesktopSwitching() const;
bool isDesktopSwitchingMovingClients() const;
@ -364,8 +366,10 @@ public:
return m_gestureRecognizer;
}
#if KWIN_BUILD_X11
bool handleDndNotify(xcb_window_t window, const QPoint &point);
bool handleEnterNotifiy(xcb_window_t window, const QPoint &point, const QDateTime &timestamp);
#endif
bool remainActiveOnFullscreen() const;
const std::vector<std::unique_ptr<Edge>> &edges() const;

View file

@ -16,11 +16,14 @@
#include "outline.h"
#include "tiles/tilemanager.h"
#include "virtualdesktops.h"
#include "window.h"
#include "workspace.h"
#include "x11window.h"
#if KWIN_BUILD_ACTIVITIES
#include "activities.h"
#endif
#if KWIN_BUILD_X11
#include "x11window.h"
#endif
#include <QQmlEngine>
@ -292,12 +295,14 @@ void WorkspaceWrapper::raiseWindow(KWin::Window *window)
}
}
#if KWIN_BUILD_X11
Window *WorkspaceWrapper::getClient(qulonglong windowId)
{
auto window = Workspace::self()->findClient(Predicate::WindowMatch, windowId);
QQmlEngine::setObjectOwnership(window, QQmlEngine::CppOwnership);
return window;
}
#endif
QList<KWin::Window *> WorkspaceWrapper::windowAt(const QPointF &pos, int count) const
{

View file

@ -240,12 +240,14 @@ public:
* @param window The Window to raise
*/
Q_INVOKABLE void raiseWindow(KWin::Window *window);
#if KWIN_BUILD_X11
/**
* Finds the Client with the given @p windowId.
* @param windowId The window Id of the Client
* @return The found Client or @c null
*/
Q_SCRIPTABLE KWin::Window *getClient(qulonglong windowId);
#endif
/**
* Finds up to count windows at a particular location,
* prioritizing the topmost one first. A negative count

View file

@ -9,13 +9,16 @@
*/
#include "shadow.h"
// kwin
#include "atoms.h"
#include "core/graphicsbufferview.h"
#include "internalwindow.h"
#include "wayland/shadow.h"
#include "wayland/surface.h"
#include "wayland_server.h"
#include "window.h"
#if KWIN_BUILD_X11
#include "atoms.h"
#include "x11window.h"
#endif
#include <KDecoration2/Decoration>
#include <KDecoration2/DecorationShadow>
@ -45,15 +48,18 @@ std::unique_ptr<Shadow> Shadow::createShadow(Window *window)
if (!shadow && waylandServer()) {
shadow = createShadowFromWayland(window);
}
#if KWIN_BUILD_X11
if (!shadow && kwinApp()->x11Connection()) {
shadow = createShadowFromX11(window);
}
#endif
if (!shadow) {
shadow = createShadowFromInternalWindow(window);
}
return shadow;
}
#if KWIN_BUILD_X11
std::unique_ptr<Shadow> Shadow::createShadowFromX11(Window *window)
{
X11Window *x11Window = qobject_cast<X11Window *>(window);
@ -71,6 +77,7 @@ std::unique_ptr<Shadow> Shadow::createShadowFromX11(Window *window)
return nullptr;
}
}
#endif
std::unique_ptr<Shadow> Shadow::createShadowFromDecoration(Window *window)
{
@ -118,6 +125,7 @@ std::unique_ptr<Shadow> Shadow::createShadowFromInternalWindow(Window *window)
return shadow;
}
#if KWIN_BUILD_X11
QList<uint32_t> Shadow::readX11ShadowProperty(xcb_window_t id)
{
QList<uint32_t> ret;
@ -133,9 +141,11 @@ QList<uint32_t> Shadow::readX11ShadowProperty(xcb_window_t id)
}
return ret;
}
#endif
bool Shadow::init(const QList<uint32_t> &data)
{
#if KWIN_BUILD_X11
QList<Xcb::WindowGeometry> pixmapGeometries(ShadowElementsCount);
QList<xcb_get_image_cookie_t> getImageCookies(ShadowElementsCount);
auto *c = kwinApp()->x11Connection();
@ -167,6 +177,7 @@ bool Shadow::init(const QList<uint32_t> &data)
m_shadowElements[i] = image.copy();
free(reply);
}
#endif
m_offset = QMargins(data[ShadowElementsCount + 3],
data[ShadowElementsCount],
data[ShadowElementsCount + 1],
@ -295,6 +306,7 @@ bool Shadow::updateShadow()
}
}
#if KWIN_BUILD_X11
if (X11Window *window = qobject_cast<X11Window *>(m_window)) {
auto data = Shadow::readX11ShadowProperty(window->window());
if (!data.isEmpty()) {
@ -302,6 +314,7 @@ bool Shadow::updateShadow()
return true;
}
}
#endif
return false;
}

View file

@ -18,9 +18,11 @@
#include "virtualdesktops.h"
#include "wayland_server.h"
#include "workspace.h"
#include "x11window.h"
#include "xdgshellwindow.h"
#include <QDebug>
#if KWIN_BUILD_X11
#include "x11window.h"
#endif
#include <QSessionManager>
#if KWIN_BUILD_NOTIFICATIONS
@ -95,6 +97,7 @@ void SessionManager::storeSession(const QString &sessionName, SMSavePhase phase)
int count = 0;
int active_client = -1;
#if KWIN_BUILD_X11
const QList<Window *> windows = workspace()->windows();
for (auto it = windows.begin(); it != windows.end(); ++it) {
X11Window *c = qobject_cast<X11Window *>(*it);
@ -123,6 +126,7 @@ void SessionManager::storeSession(const QString &sessionName, SMSavePhase phase)
storeClient(cg, count, c);
}
}
#endif
if (phase == SMSavePhase0) {
// it would be much simpler to save these values to the config file,
// but both Qt and KDE treat phase1 and phase2 separately,
@ -141,6 +145,7 @@ void SessionManager::storeSession(const QString &sessionName, SMSavePhase phase)
config->sync(); // it previously did some "revert to defaults" stuff for phase1 I think
}
#if KWIN_BUILD_X11
void SessionManager::storeClient(KConfigGroup &cg, int num, X11Window *c)
{
c->setSessionActivityOverride(false); // make sure we get the real values
@ -176,7 +181,9 @@ void SessionManager::storeClient(KConfigGroup &cg, int num, X11Window *c)
cg.writeEntry(QLatin1String("stackingOrder") + n, workspace()->unconstrainedStackingOrder().indexOf(c));
cg.writeEntry(QLatin1String("activities") + n, c->activities());
}
#endif
#if KWIN_BUILD_X11
void SessionManager::storeSubSession(const QString &name, QSet<QByteArray> sessionIds)
{
// TODO clear it first
@ -217,6 +224,7 @@ void SessionManager::storeSubSession(const QString &name, QSet<QByteArray> sessi
cg.writeEntry("active", active_client);
// cg.writeEntry( "desktop", currentDesktop());
}
#endif
/**
* Loads the session information from the config file.
@ -275,6 +283,7 @@ void SessionManager::loadSubSessionInfo(const QString &name)
addSessionInfo(cg);
}
#if KWIN_BUILD_X11
static bool sessionInfoWindowTypeMatch(X11Window *c, SessionInfo *info)
{
if (int(info->windowType) == -2) {
@ -343,6 +352,7 @@ SessionInfo *SessionManager::takeSessionInfo(X11Window *c)
}
return realInfo;
}
#endif
SessionManager::SessionManager(QObject *parent)
: QObject(parent)
@ -388,9 +398,11 @@ void SessionManager::setState(SessionState state)
// If we're ending a save session due to either completion or cancellation
if (m_sessionState == SessionState::Saving) {
workspace()->rulebook()->setUpdatesDisabled(false);
#if KWIN_BUILD_X11
Workspace::self()->forEachClient([](X11Window *client) {
client->setSessionActivityOverride(false);
});
#endif
}
m_sessionState = state;

View file

@ -43,9 +43,11 @@ public:
SessionState state() const;
void loadSubSessionInfo(const QString &name);
void storeSubSession(const QString &name, QSet<QByteArray> sessionIds);
#if KWIN_BUILD_X11
void storeSubSession(const QString &name, QSet<QByteArray> sessionIds);
SessionInfo *takeSessionInfo(X11Window *);
#endif
Q_SIGNALS:
void stateChanged();
@ -66,7 +68,9 @@ private:
void setState(SessionState state);
void storeSession(const QString &sessionName, SMSavePhase phase);
#if KWIN_BUILD_X11
void storeClient(KConfigGroup &cg, int num, X11Window *c);
#endif
void loadSessionInfo(const QString &sessionName);
void addSessionInfo(KConfigGroup &cg);

View file

@ -16,7 +16,6 @@
#include "tabbox/clientmodel.h"
#include "tabbox/tabbox_logging.h"
#include "tabbox/tabboxconfig.h"
#include "tabbox/x11_filter.h"
// kwin
#if KWIN_BUILD_ACTIVITIES
#include "activities.h"
@ -28,10 +27,12 @@
#include "keyboard_input.h"
#include "pointer_input.h"
#include "screenedge.h"
#include "utils/xcbutils.h"
#include "virtualdesktops.h"
#include "window.h"
#include "workspace.h"
#if KWIN_BUILD_X11
#include "x11window.h"
#endif
// Qt
#include <QAction>
#include <QKeyEvent>
@ -42,12 +43,15 @@
#include <KLazyLocalizedString>
#include <KLocalizedString>
#include <kkeyserver.h>
#if KWIN_BUILD_X11
#include "tabbox/x11_filter.h"
#include "utils/xcbutils.h"
// X11
#include <X11/keysym.h>
#include <X11/keysymdef.h>
// xcb
#include <xcb/xcb_keysyms.h>
#endif
// specify externals before namespace
namespace KWin
@ -666,6 +670,7 @@ void TabBox::grabbedKeyEvent(QKeyEvent *event)
m_tabBox->grabbedKeyEvent(event);
}
#if KWIN_BUILD_X11
struct KeySymbolsDeleter
{
void operator()(xcb_key_symbols_t *symbols)
@ -751,6 +756,7 @@ static bool areModKeysDepressedX11(const QKeySequence &seq)
return areKeySymXsDepressed(rgKeySyms, nKeySyms);
}
#endif
static bool areModKeysDepressedWayland(const QKeySequence &seq)
{
@ -776,11 +782,15 @@ static bool areModKeysDepressed(const QKeySequence &seq)
if (seq.isEmpty()) {
return false;
}
#if KWIN_BUILD_X11
if (kwinApp()->shouldUseWaylandForCompositing()) {
return areModKeysDepressedWayland(seq);
} else {
return areModKeysDepressedX11(seq);
}
#else
return areModKeysDepressedWayland(seq);
#endif
}
void TabBox::navigatingThroughWindows(bool forward, const QKeySequence &shortcut, TabBoxMode mode)
@ -1178,10 +1188,12 @@ bool TabBox::establishTabBoxGrab()
m_forcedGlobalMouseGrab = true;
return true;
}
#if KWIN_BUILD_X11
kwinApp()->updateXTime();
if (!grabXKeyboard()) {
return false;
}
#endif
// Don't try to establish a global mouse grab using XGrabPointer, as that would prevent
// using Alt+Tab while DND (#44972). However force passive grabs on all windows
// in order to catch MouseRelease events and close the tabbox (#67416).
@ -1192,7 +1204,9 @@ bool TabBox::establishTabBoxGrab()
if (Workspace::self()->activeWindow() != nullptr) {
Workspace::self()->activeWindow()->updateMouseGrab();
}
#if KWIN_BUILD_X11
m_x11EventFilter = std::make_unique<X11Filter>();
#endif
return true;
}
@ -1202,14 +1216,19 @@ void TabBox::removeTabBoxGrab()
m_forcedGlobalMouseGrab = false;
return;
}
#if KWIN_BUILD_X11
kwinApp()->updateXTime();
ungrabXKeyboard();
#endif
Q_ASSERT(m_forcedGlobalMouseGrab);
m_forcedGlobalMouseGrab = false;
if (Workspace::self()->activeWindow() != nullptr) {
Workspace::self()->activeWindow()->updateMouseGrab();
}
#if KWIN_BUILD_X11
m_x11EventFilter.reset();
#endif
}
} // namespace TabBox
} // namespace

View file

@ -273,7 +273,10 @@ private:
QList<ElectricBorder> m_borderActivate, m_borderAlternativeActivate;
QHash<ElectricBorder, QAction *> m_touchActivate;
QHash<ElectricBorder, QAction *> m_touchAlternativeActivate;
#if KWIN_BUILD_X11
std::unique_ptr<X11EventFilter> m_x11EventFilter;
#endif
};
} // namespace TabBox

View file

@ -32,8 +32,11 @@
#include "scripting/scripting.h"
#include "useractions.h"
#include "virtualdesktops.h"
#include "window.h"
#include "workspace.h"
#if KWIN_BUILD_X11
#include "x11window.h"
#endif
#if KWIN_BUILD_ACTIVITIES
#include "activities.h"
@ -46,6 +49,7 @@
#include <QAction>
#include <QCheckBox>
#include <QPushButton>
#include <QWindow>
#include <KGlobalAccel>
#include <KLazyLocalizedString>
@ -1819,19 +1823,6 @@ void Window::setShortcutInternal()
workspace()->windowShortcutUpdated(this);
}
void X11Window::setShortcutInternal()
{
updateCaption();
#if 0
workspace()->windowShortcutUpdated(this);
#else
// Workaround for kwin<->kglobalaccel deadlock, when KWin has X grab and the kded
// kglobalaccel module tries to create the key grab. KWin should preferably grab
// they keys itself anyway :(.
QTimer::singleShot(0, this, std::bind(&Workspace::windowShortcutUpdated, workspace(), this));
#endif
}
bool Workspace::shortcutAvailable(const QKeySequence &cut, Window *ignore) const
{
if (ignore && cut == ignore->shortcut()) {

View file

@ -10,9 +10,11 @@ target_sources(kwin PRIVATE
subsurfacemonitor.cpp
udev.cpp
vsyncmonitor.cpp
xcbutils.cpp
xcursortheme.cpp
)
if (KWIN_BUILD_X11)
target_sources(kwin PRIVATE xcbutils.cpp)
endif()
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
target_sources(kwin PRIVATE executable_path_proc.cpp)

View file

@ -15,12 +15,15 @@
*/
#include "utils/common.h"
#include "effect/xcb.h"
#include "utils/c_ptr.h"
#if KWIN_BUILD_X11
#include "effect/xcb.h"
#include <kkeyserver.h>
#endif
#include <QPainter>
#include <QWidget>
#include <kkeyserver.h>
#ifndef KCMRULES
#include <QApplication>
@ -67,6 +70,8 @@ StrutRect &StrutRect::operator=(const StrutRect &other)
return *this;
}
#if KWIN_BUILD_X11
static int server_grab_count = 0;
void grabXServer()
@ -128,8 +133,6 @@ void ungrabXKeyboard()
xcb_ungrab_keyboard(connection(), XCB_TIME_CURRENT_TIME);
}
#endif
// converting between X11 mouse/keyboard state mask and Qt button/keyboard states
Qt::MouseButton x11ToQtMouseButton(int button)
@ -191,6 +194,61 @@ Qt::KeyboardModifiers x11ToQtKeyboardModifiers(int state)
return ret;
}
#endif
#endif
QPointF popupOffset(const QRectF &anchorRect, const Qt::Edges anchorEdge, const Qt::Edges gravity, const QSizeF popupSize)
{
QPointF anchorPoint;
switch (anchorEdge & (Qt::LeftEdge | Qt::RightEdge)) {
case Qt::LeftEdge:
anchorPoint.setX(anchorRect.x());
break;
case Qt::RightEdge:
anchorPoint.setX(anchorRect.x() + anchorRect.width());
break;
default:
anchorPoint.setX(qRound(anchorRect.x() + anchorRect.width() / 2.0));
}
switch (anchorEdge & (Qt::TopEdge | Qt::BottomEdge)) {
case Qt::TopEdge:
anchorPoint.setY(anchorRect.y());
break;
case Qt::BottomEdge:
anchorPoint.setY(anchorRect.y() + anchorRect.height());
break;
default:
anchorPoint.setY(qRound(anchorRect.y() + anchorRect.height() / 2.0));
}
// calculate where the top left point of the popup will end up with the applied gravity
// gravity indicates direction. i.e if gravitating towards the top the popup's bottom edge
// will next to the anchor point
QPointF popupPosAdjust;
switch (gravity & (Qt::LeftEdge | Qt::RightEdge)) {
case Qt::LeftEdge:
popupPosAdjust.setX(-popupSize.width());
break;
case Qt::RightEdge:
popupPosAdjust.setX(0);
break;
default:
popupPosAdjust.setX(qRound(-popupSize.width() / 2.0));
}
switch (gravity & (Qt::TopEdge | Qt::BottomEdge)) {
case Qt::TopEdge:
popupPosAdjust.setY(-popupSize.height());
break;
case Qt::BottomEdge:
popupPosAdjust.setY(0);
break;
default:
popupPosAdjust.setY(qRound(-popupSize.height() / 2.0));
}
return anchorPoint + popupPosAdjust;
}
QRectF gravitateGeometry(const QRectF &rect, const QRectF &bounds, Gravity gravity)
{
QRectF geometry = rect;
@ -223,6 +281,3 @@ QRectF gravitateGeometry(const QRectF &rect, const QRectF &bounds, Gravity gravi
}
} // namespace
#ifndef KCMRULES
#endif

View file

@ -84,11 +84,13 @@ inline MaximizeMode operator^(MaximizeMode m1, MaximizeMode m2)
return MaximizeMode(int(m1) ^ int(m2));
}
#if KWIN_BUILD_X11
// converting between X11 mouse/keyboard state mask and Qt button/keyboard states
Qt::MouseButton x11ToQtMouseButton(int button);
Qt::MouseButton KWIN_EXPORT x11ToQtMouseButton(int button);
Qt::MouseButtons KWIN_EXPORT x11ToQtMouseButtons(int state);
Qt::KeyboardModifiers KWIN_EXPORT x11ToQtKeyboardModifiers(int state);
#endif
KWIN_EXPORT QRectF gravitateGeometry(const QRectF &rect, const QRectF &bounds, Gravity gravity);

View file

@ -8,6 +8,12 @@
*/
#pragma once
#include "config-kwin.h"
#if !KWIN_BUILD_X11
#error Do not include on non-X11 builds
#endif
#include "effect/globals.h"
#include "effect/xcb.h"
#include "main.h"

View file

@ -14,7 +14,9 @@
#include <KConfigGroup>
#include <KGlobalAccel>
#include <KLocalizedString>
#if KWIN_BUILD_X11
#include <NETWM>
#endif
// Qt
#include <QAction>
@ -196,7 +198,9 @@ KWIN_SINGLETON_FACTORY_VARIABLE(VirtualDesktopManager, s_manager)
VirtualDesktopManager::VirtualDesktopManager(QObject *parent)
: QObject(parent)
, m_navigationWrapsAround(false)
#if KWIN_BUILD_X11
, m_rootInfo(nullptr)
#endif
, m_swipeGestureReleasedY(new QAction(this))
, m_swipeGestureReleasedX(new QAction(this))
{
@ -209,6 +213,7 @@ VirtualDesktopManager::~VirtualDesktopManager()
void VirtualDesktopManager::setRootInfo(NETRootInfo *info)
{
#if KWIN_BUILD_X11
m_rootInfo = info;
// Nothing will be connected to rootInfo
@ -219,6 +224,7 @@ void VirtualDesktopManager::setRootInfo(NETRootInfo *info)
m_rootInfo->setDesktopName(vd->x11DesktopNumber(), vd->name().toUtf8().data());
}
}
#endif
}
VirtualDesktop *VirtualDesktopManager::inDirection(VirtualDesktop *desktop, Direction direction, bool wrap)
@ -428,6 +434,7 @@ VirtualDesktop *VirtualDesktopManager::createVirtualDesktop(uint position, const
vd->setId(generateDesktopId());
vd->setName(desktopName);
#if KWIN_BUILD_X11
connect(vd, &VirtualDesktop::nameChanged, this, [this, vd]() {
if (m_rootInfo) {
m_rootInfo->setDesktopName(vd->x11DesktopNumber(), vd->name().toUtf8().data());
@ -437,15 +444,18 @@ VirtualDesktop *VirtualDesktopManager::createVirtualDesktop(uint position, const
if (m_rootInfo) {
m_rootInfo->setDesktopName(vd->x11DesktopNumber(), vd->name().toUtf8().data());
}
#endif
m_desktops.insert(position, vd);
// update the id of displaced desktops
for (uint i = position + 1; i < (uint)m_desktops.count(); ++i) {
m_desktops[i]->setX11DesktopNumber(i + 1);
#if KWIN_BUILD_X11
if (m_rootInfo) {
m_rootInfo->setDesktopName(i + 1, m_desktops[i]->name().toUtf8().data());
}
#endif
}
save();
@ -477,9 +487,11 @@ void VirtualDesktopManager::removeVirtualDesktop(VirtualDesktop *desktop)
for (int j = i; j < m_desktops.count(); ++j) {
m_desktops[j]->setX11DesktopNumber(j + 1);
#if KWIN_BUILD_X11
if (m_rootInfo) {
m_rootInfo->setDesktopName(j + 1, m_desktops[j]->name().toUtf8().data());
}
#endif
}
if (m_current == desktop) {
@ -562,6 +574,7 @@ void VirtualDesktopManager::setCount(uint count)
}
m_desktops << vd;
newDesktops << vd;
#if KWIN_BUILD_X11
connect(vd, &VirtualDesktop::nameChanged, this, [this, vd]() {
if (m_rootInfo) {
m_rootInfo->setDesktopName(vd->x11DesktopNumber(), vd->name().toUtf8().data());
@ -570,6 +583,7 @@ void VirtualDesktopManager::setCount(uint count)
if (m_rootInfo) {
m_rootInfo->setDesktopName(vd->x11DesktopNumber(), vd->name().toUtf8().data());
}
#endif
}
}
@ -608,6 +622,7 @@ void VirtualDesktopManager::setRows(uint rows)
void VirtualDesktopManager::updateRootInfo()
{
#if KWIN_BUILD_X11
if (m_rootInfo) {
const int n = count();
m_rootInfo->setNumberOfDesktops(n);
@ -616,6 +631,7 @@ void VirtualDesktopManager::updateRootInfo()
delete[] viewports;
m_rootInfo->setDesktopLayout(NET::OrientationHorizontal, m_grid.width(), m_grid.height(), NET::DesktopLayoutCornerTopLeft);
}
#endif
}
void VirtualDesktopManager::updateLayout()
@ -646,9 +662,11 @@ void VirtualDesktopManager::load()
for (int i = 1; i <= n; i++) {
QString s = group.readEntry(QStringLiteral("Name_%1").arg(i), i18n("Desktop %1", i));
#if KWIN_BUILD_X11
if (m_rootInfo) {
m_rootInfo->setDesktopName(i, s.toUtf8().data());
}
#endif
m_desktops[i - 1]->setName(s);
const QString sId = group.readEntry(QStringLiteral("Id_%1").arg(i), QString());
@ -692,9 +710,11 @@ void VirtualDesktopManager::save()
const QString defaultvalue = defaultName(position);
if (s.isEmpty()) {
s = defaultvalue;
#if KWIN_BUILD_X11
if (m_rootInfo) {
m_rootInfo->setDesktopName(position, s.toUtf8().data());
}
#endif
}
if (s != defaultvalue) {

View file

@ -481,7 +481,9 @@ private:
bool m_navigationWrapsAround;
VirtualDesktopGrid m_grid;
// TODO: QPointer
#if KWIN_BUILD_X11
NETRootInfo *m_rootInfo;
#endif
PlasmaVirtualDesktopManagementInterface *m_virtualDesktopManagement = nullptr;
KSharedConfig::Ptr m_config;

View file

@ -71,14 +71,16 @@
#include "wayland/xdgoutput_v1.h"
#include "wayland/xdgshell.h"
#include "wayland/xdgtopleveldrag_v1.h"
#include "wayland/xwaylandkeyboardgrab_v1.h"
#include "wayland/xwaylandshell_v1.h"
#include "wayland/xx_colormanagement_v2.h"
#include "workspace.h"
#include "x11window.h"
#include "xdgactivationv1.h"
#include "xdgshellintegration.h"
#include "xdgshellwindow.h"
#if KWIN_BUILD_X11
#include "wayland/xwaylandkeyboardgrab_v1.h"
#include "wayland/xwaylandshell_v1.h"
#include "x11window.h"
#endif
// Qt
#include <QDir>
@ -310,6 +312,7 @@ bool WaylandServer::init(InitializationFlags flags)
{
m_initFlags = flags;
m_compositor = new CompositorInterface(m_display, m_display);
#if KWIN_BUILD_X11
connect(m_compositor, &CompositorInterface::surfaceCreated, this, [this](SurfaceInterface *surface) {
// check whether we have a Window with the Surface's id
Workspace *ws = Workspace::self();
@ -359,6 +362,7 @@ bool WaylandServer::init(InitializationFlags flags)
return;
}
});
#endif
m_tabletManagerV2 = new TabletManagerV2Interface(m_display, m_display);
m_keyboardShortcutsInhibitManager = new KeyboardShortcutsInhibitManagerV1Interface(m_display, m_display);
@ -455,7 +459,9 @@ bool WaylandServer::init(InitializationFlags flags)
new SubCompositorInterface(m_display, m_display);
m_XdgForeign = new XdgForeignV2Interface(m_display, m_display);
m_inputMethod = new InputMethodV1Interface(m_display, m_display);
#if KWIN_BUILD_X11
m_xWaylandKeyboardGrabManager = new XWaylandKeyboardGrabManagerV1Interface(m_display, m_display);
#endif
auto activation = new XdgActivationV1Interface(m_display, this);
auto init = [this, activation] {
@ -677,6 +683,7 @@ int WaylandServer::createScreenLockerConnection()
return socket.fd;
}
#if KWIN_BUILD_X11
int WaylandServer::createXWaylandConnection()
{
const auto socket = createConnection();
@ -701,6 +708,7 @@ void WaylandServer::destroyXWaylandConnection()
m_xwaylandConnection->destroy();
m_xwaylandConnection = nullptr;
}
#endif
int WaylandServer::createInputMethodConnection()
{
@ -795,9 +803,11 @@ bool WaylandServer::isKeyboardShortcutsInhibited() const
if (inhibitor && inhibitor->isActive()) {
return true;
}
#if KWIN_BUILD_X11
if (m_xWaylandKeyboardGrabManager->hasGrab(surface, seat())) {
return true;
}
#endif
}
return false;
}

View file

@ -123,10 +123,12 @@ public:
{
return m_keyboardShortcutsInhibitManager;
}
#if KWIN_BUILD_X11
XwaylandShellV1Interface *xwaylandShell() const
{
return m_xwaylandShell;
}
#endif
bool isKeyboardShortcutsInhibited() const;
@ -160,11 +162,13 @@ public:
*/
XdgExportedSurface *exportAsForeign(SurfaceInterface *surface);
#if KWIN_BUILD_X11
/**
* @returns file descriptor for Xwayland to connect to.
*/
int createXWaylandConnection();
void destroyXWaylandConnection();
#endif
/**
* @returns file descriptor to the input method server's socket.
@ -279,7 +283,9 @@ private:
ClientConnection *m_screenLockerClientConnection = nullptr;
XdgForeignV2Interface *m_XdgForeign = nullptr;
XdgActivationV1Integration *m_xdgActivationIntegration = nullptr;
#if KWIN_BUILD_X11
XWaylandKeyboardGrabManagerV1Interface *m_xWaylandKeyboardGrabManager = nullptr;
#endif
ContentTypeManagerV1Interface *m_contentTypeManager = nullptr;
TearingControlManagerV1Interface *m_tearingControlInterface = nullptr;
XwaylandShellV1Interface *m_xwaylandShell = nullptr;

View file

@ -19,19 +19,16 @@
#include "activities.h"
#endif
#include "appmenu.h"
#include "atoms.h"
#include "core/outputbackend.h"
#include "core/outputconfiguration.h"
#include "cursor.h"
#include "dbusinterface.h"
#include "effect/effecthandler.h"
#include "focuschain.h"
#include "group.h"
#include "input.h"
#include "internalwindow.h"
#include "killwindow.h"
#include "moving_client_x11_filter.h"
#include "netinfo.h"
#include "outline.h"
#include "placement.h"
#include "pluginmanager.h"
@ -40,7 +37,7 @@
#include "scripting/scripting.h"
#include "syncalarmx11filter.h"
#include "tiles/tilemanager.h"
#include "x11window.h"
#include "window.h"
#if KWIN_BUILD_TABBOX
#include "tabbox/tabbox.h"
#endif
@ -57,15 +54,21 @@
#include "useractions.h"
#include "utils/kernel.h"
#include "utils/orientationsensor.h"
#include "utils/xcbutils.h"
#include "virtualdesktops.h"
#include "was_user_interaction_x11_filter.h"
#include "wayland_server.h"
#if KWIN_BUILD_X11
#include "atoms.h"
#include "group.h"
#include "netinfo.h"
#include "utils/xcbutils.h"
#include "x11window.h"
#include <KStartupInfo>
#endif
// KDE
#include <KConfig>
#include <KConfigGroup>
#include <KLocalizedString>
#include <KStartupInfo>
// Qt
#include <QCryptographicHash>
#include <QDBusConnection>
@ -217,11 +220,13 @@ void Workspace::init()
m_activeWindow = nullptr;
#if KWIN_BUILD_X11
// We want to have some xcb connection while tearing down X11 components. We don't really
// care if the xcb connection is broken or has an error.
connect(kwinApp(), &Application::x11ConnectionChanged, this, &Workspace::initializeX11);
connect(kwinApp(), &Application::x11ConnectionAboutToBeDestroyed, this, &Workspace::cleanupX11);
initializeX11();
#endif
Scripting::create(this);
@ -272,6 +277,7 @@ QString Workspace::getPlacementTrackerHash()
return QString::fromLatin1(hash.toHex());
}
#if KWIN_BUILD_X11
void Workspace::initializeX11()
{
if (!kwinApp()->x11Connection()) {
@ -437,12 +443,15 @@ void Workspace::cleanupX11()
m_syncAlarmFilter.reset();
m_wasUserInteractionFilter.reset();
}
#endif
Workspace::~Workspace()
{
blockStackingUpdates(true);
#if KWIN_BUILD_X11
cleanupX11();
#endif
if (waylandServer()) {
const QList<Window *> waylandWindows = waylandServer()->windows();
@ -660,6 +669,7 @@ void Workspace::removeFromStack(Window *window)
}
}
#if KWIN_BUILD_X11
X11Window *Workspace::createX11Window(xcb_window_t windowId, bool is_mapped)
{
StackingUpdatesBlocker blocker(this);
@ -722,7 +732,7 @@ void Workspace::addX11Window(X11Window *window)
}
window->checkActiveModal();
checkTransients(window->window()); // SELI TODO: Does this really belong here?
updateStackingOrder(true); // Propagate new window
updateStackingOrder(true); // Propagatem new window
if (window->isUtility() || window->isMenu() || window->isToolbar()) {
updateToolWindows(true);
}
@ -759,6 +769,7 @@ void Workspace::removeUnmanaged(X11Window *window)
updateStackingOrder();
Q_EMIT windowRemoved(window);
}
#endif
void Workspace::addDeleted(Window *c)
{
@ -861,11 +872,13 @@ void Workspace::updateToolWindows(bool also_hide)
{
// TODO: What if Client's transiency/group changes? should this be called too? (I'm paranoid, am I not?)
if (!options->isHideUtilityWindowsForInactive()) {
#if KWIN_BUILD_X11
for (auto it = m_windows.constBegin(); it != m_windows.constEnd(); ++it) {
if (X11Window *x11Window = qobject_cast<X11Window *>(*it)) {
x11Window->setHidden(false);
}
}
#endif
return;
}
const Group *group = nullptr;
@ -895,11 +908,14 @@ void Workspace::updateToolWindows(bool also_hide)
if (c->isUtility() || c->isMenu() || c->isToolbar()) {
bool show = true;
if (!c->isTransient()) {
#if KWIN_BUILD_X11
if (!c->group() || c->group()->members().count() == 1) { // Has its own group, keep always visible
show = true;
} else if (window != nullptr && c->group() == window->group()) {
show = true;
} else {
} else
#endif
{
show = false;
}
} else {
@ -1030,6 +1046,7 @@ void Workspace::slotCurrentDesktopChangingCancelled()
void Workspace::updateWindowVisibilityOnDesktopChange(VirtualDesktop *newDesktop)
{
#if KWIN_BUILD_X11
for (auto it = stacking_order.constBegin(); it != stacking_order.constEnd(); ++it) {
X11Window *c = qobject_cast<X11Window *>(*it);
if (!c) {
@ -1043,11 +1060,13 @@ void Workspace::updateWindowVisibilityOnDesktopChange(VirtualDesktop *newDesktop
if (rootInfo()) {
rootInfo()->setCurrentDesktop(VirtualDesktopManager::self()->current());
}
#endif
if (m_moveResizeWindow && !m_moveResizeWindow->isOnDesktop(newDesktop)) {
m_moveResizeWindow->setDesktops({newDesktop});
}
#if KWIN_BUILD_X11
for (int i = stacking_order.size() - 1; i >= 0; --i) {
X11Window *c = qobject_cast<X11Window *>(stacking_order.at(i));
if (!c) {
@ -1057,6 +1076,7 @@ void Workspace::updateWindowVisibilityOnDesktopChange(VirtualDesktop *newDesktop
c->updateVisibility();
}
}
#endif
if (showingDesktop()) { // Do this only after desktop change to avoid flicker
setShowingDesktop(false);
}
@ -1142,6 +1162,7 @@ void Workspace::updateCurrentActivity(const QString &new_activity)
// mapping done from front to back => less exposure events
// Notify::raise((Notify::Event) (Notify::DesktopChange+new_desktop));
#if KWIN_BUILD_X11
for (auto it = stacking_order.constBegin(); it != stacking_order.constEnd(); ++it) {
X11Window *window = qobject_cast<X11Window *>(*it);
if (!window) {
@ -1170,6 +1191,7 @@ void Workspace::updateCurrentActivity(const QString &new_activity)
window->updateVisibility();
}
}
#endif
// FIXME not sure if I should do this either
if (showingDesktop()) { // Do this only after desktop change to avoid flicker
@ -1458,6 +1480,7 @@ void Workspace::slotDesktopRemoved(VirtualDesktop *desktop)
m_focusChain->removeDesktop(desktop);
}
#if KWIN_BUILD_X11
void Workspace::selectWmInputEventMask()
{
uint32_t presentMask = 0;
@ -1476,6 +1499,7 @@ void Workspace::selectWmInputEventMask()
Xcb::selectInput(kwinApp()->x11RootWindow(), presentMask | wmMask);
}
#endif
/**
* Sends window \a window to desktop \a desk.
@ -1542,10 +1566,12 @@ void Workspace::cancelDelayFocus()
m_delayFocusWindow = nullptr;
}
#if KWIN_BUILD_X11
bool Workspace::checkStartupNotification(xcb_window_t w, KStartupInfoId &id, KStartupInfoData &data)
{
return m_startup->checkStartup(w, id, data) == KStartupInfo::Match;
}
#endif
/**
* Puts the focus on a dummy window
@ -1553,10 +1579,12 @@ bool Workspace::checkStartupNotification(xcb_window_t w, KStartupInfoId &id, KSt
*/
void Workspace::focusToNull()
{
#if KWIN_BUILD_X11
if (m_nullFocus) {
should_get_focus.clear();
m_nullFocus->focus();
}
#endif
}
bool Workspace::breaksShowingDesktop(Window *window) const
@ -1567,9 +1595,12 @@ bool Workspace::breaksShowingDesktop(Window *window) const
void Workspace::setShowingDesktop(bool showing, bool animated)
{
const bool changed = showing != showing_desktop;
#if KWIN_BUILD_X11
if (rootInfo() && changed) {
rootInfo()->setShowingDesktop(showing);
}
#endif
showing_desktop = showing;
for (int i = stacking_order.count() - 1; i > -1; --i) {
@ -1674,6 +1705,7 @@ QString Workspace::supportInformation() const
support.append(HAVE_GLX ? yes : no);
support.append(QStringLiteral("\n"));
#if KWIN_BUILD_X11
if (auto c = kwinApp()->x11Connection()) {
support.append(QStringLiteral("X11\n"));
support.append(QStringLiteral("===\n"));
@ -1688,6 +1720,7 @@ QString Workspace::supportInformation() const
}
support.append(QStringLiteral("\n"));
}
#endif
if (m_decorationBridge) {
support.append(QStringLiteral("Decoration\n"));
@ -1823,9 +1856,11 @@ QString Workspace::supportInformation() const
if (platform->isMesaDriver()) {
support.append(QStringLiteral("Mesa version: ") + platform->mesaVersion().toString() + QStringLiteral("\n"));
}
#if KWIN_BUILD_X11
if (auto xVersion = Xcb::xServerVersion(); xVersion.isValid()) {
support.append(QStringLiteral("X server version: ") + xVersion.toString() + QStringLiteral("\n"));
}
#endif
if (auto kernelVersion = linuxKernelVersion(); kernelVersion.isValid()) {
support.append(QStringLiteral("Linux kernel version: ") + kernelVersion.toString() + QStringLiteral("\n"));
}
@ -1892,6 +1927,7 @@ QString Workspace::supportInformation() const
return support;
}
#if KWIN_BUILD_X11
void Workspace::forEachClient(std::function<void(X11Window *)> func)
{
for (Window *window : std::as_const(m_windows)) {
@ -1953,6 +1989,7 @@ X11Window *Workspace::findClient(Predicate predicate, xcb_window_t w) const
}
return nullptr;
}
#endif
Window *Workspace::findWindow(std::function<bool(const Window *)> func) const
{
@ -1984,9 +2021,11 @@ Window *Workspace::findInternal(QWindow *w) const
if (!w) {
return nullptr;
}
#if KWIN_BUILD_X11
if (kwinApp()->operationMode() == Application::OperationModeX11) {
return findUnmanaged(w->winId());
}
#endif
for (Window *window : m_windows) {
if (InternalWindow *internal = qobject_cast<InternalWindow *>(window)) {
if (internal->handle() == w) {
@ -2004,10 +2043,12 @@ void Workspace::setWasUserInteraction()
}
was_user_interaction = true;
// might be called from within the filter, so delay till we now the filter returned
#if KWIN_BUILD_X11
QTimer::singleShot(0, this,
[this] {
m_wasUserInteractionFilter.reset();
});
#endif
}
void Workspace::updateTabbox()
@ -2050,6 +2091,7 @@ void Workspace::setInitialDesktop(int desktop)
m_initialDesktop = desktop;
}
#if KWIN_BUILD_X11
Group *Workspace::findGroup(xcb_window_t leader) const
{
Q_ASSERT(leader != XCB_WINDOW_NONE);
@ -2092,6 +2134,7 @@ Group *Workspace::findClientLeaderGroup(const X11Window *window) const
}
return ret;
}
#endif
void Workspace::updateMinimizedOfTransients(Window *window)
{
@ -2142,6 +2185,7 @@ void Workspace::updateOnAllDesktopsOfTransients(Window *window)
}
}
#if KWIN_BUILD_X11
// A new window has been mapped. Check if it's not a mainwindow for some already existing transient window.
void Workspace::checkTransients(xcb_window_t w)
{
@ -2151,6 +2195,7 @@ void Workspace::checkTransients(xcb_window_t w)
}
}
}
#endif
/**
* Resizes the workspace after an XRANDR screen size change
@ -2165,12 +2210,14 @@ void Workspace::desktopResized()
m_geometry = m_geometry.united(output->geometry());
}
#if KWIN_BUILD_X11
if (rootInfo()) {
NETSize desktop_geometry;
desktop_geometry.width = Xcb::toXNative(m_geometry.width());
desktop_geometry.height = Xcb::toXNative(m_geometry.height());
rootInfo()->setDesktopGeometry(desktop_geometry);
}
#endif
updateClientArea();
@ -2215,6 +2262,7 @@ void Workspace::saveOldScreenSizes()
}
}
#if KWIN_BUILD_X11
/**
* Whether or not the window has a strut that expands through the invisible area of
* an xinerama setup where the monitors are not the same resolution.
@ -2241,6 +2289,7 @@ static bool hasOffscreenXineramaStrut(Window *window)
return false;
}
#endif
QRectF Workspace::adjustClientArea(Window *window, const QRectF &area) const
{
@ -2252,6 +2301,7 @@ QRectF Workspace::adjustClientArea(Window *window, const QRectF &area) const
QRectF strutBottom = window->strutRect(StrutAreaBottom);
QRectF screenArea = clientArea(ScreenArea, window);
#if KWIN_BUILD_X11
if (qobject_cast<X11Window *>(window)) {
// HACK: workarea handling is not xinerama aware, so if this strut
// reserves place at a xinerama edge that's inside the virtual screen,
@ -2271,6 +2321,7 @@ QRectF Workspace::adjustClientArea(Window *window, const QRectF &area) const
}
}
}
#endif
// Handle struts at xinerama edges that are inside the virtual screen.
// They're given in virtual screen coordinates, make them affect only
@ -2358,7 +2409,10 @@ void Workspace::updateClientArea()
// This goes against the EWMH description of the work area but it is a toss up between
// having unusable sections of the screen (Which can be quite large with newer monitors)
// or having some content appear offscreen (Relatively rare compared to other).
bool hasOffscreenStrut = hasOffscreenXineramaStrut(window);
bool hasOffscreenStrut = false;
#if KWIN_BUILD_X11
hasOffscreenStrut = hasOffscreenXineramaStrut(window);
#endif
const auto vds = window->isOnAllDesktops() ? desktops : window->desktops();
for (VirtualDesktop *vd : vds) {
@ -2384,6 +2438,7 @@ void Workspace::updateClientArea()
m_oldRestrictedAreas = m_restrictedAreas;
m_restrictedAreas = restrictedAreas;
#if KWIN_BUILD_X11
if (rootInfo()) {
for (VirtualDesktop *desktop : desktops) {
const QRectF &workArea = m_workAreas[desktop];
@ -2391,6 +2446,7 @@ void Workspace::updateClientArea()
rootInfo()->setWorkArea(desktop->x11DesktopNumber(), r);
}
}
#endif
for (auto it = m_windows.constBegin(); it != m_windows.constEnd(); ++it) {
if ((*it)->isClient()) {
@ -2503,6 +2559,7 @@ QHash<const Output *, QRect> Workspace::previousScreenSizes() const
return m_oldScreenGeometries;
}
#if KWIN_BUILD_X11
Output *Workspace::xineramaIndexToOutput(int index) const
{
xcb_connection_t *connection = kwinApp()->x11Connection();
@ -2536,6 +2593,7 @@ Output *Workspace::xineramaIndexToOutput(int index) const
return nullptr;
}
#endif
void Workspace::setOutputOrder(const QList<Output *> &order)
{
@ -3013,6 +3071,7 @@ void Workspace::setMoveResizeWindow(Window *window)
}
}
#if KWIN_BUILD_X11
// When kwin crashes, windows will not be gravitated back to their original position
// and will remain offset by the size of the decoration. So when restarting, fix this
// (the property with the size of the frame remains on the window after the crash).
@ -3029,6 +3088,7 @@ void Workspace::fixPositionAfterCrash(xcb_window_t w, const xcb_get_geometry_rep
xcb_configure_window(kwinApp()->x11Connection(), w, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values);
}
}
#endif
FocusChain *Workspace::focusChain() const
{

View file

@ -95,10 +95,11 @@ public:
return _self;
}
bool workspaceEvent(xcb_generic_event_t *);
bool hasWindow(const Window *);
#if KWIN_BUILD_X11
bool workspaceEvent(xcb_generic_event_t *);
/**
* @brief Finds the first Client matching the condition expressed by passed in @p func.
*
@ -146,6 +147,7 @@ public:
* @return KWin::Unmanaged* Found Unmanaged or @c null if there is no Unmanaged with given Id.
*/
X11Window *findUnmanaged(xcb_window_t w) const;
#endif
Window *findWindow(const QUuid &internalId) const;
Window *findWindow(std::function<bool(const Window *)> func) const;
@ -227,14 +229,16 @@ public:
QRectF adjustWindowSize(const Window *window, QRectF moveResizeGeom, Gravity gravity) const;
void raiseWindow(Window *window, bool nogroup = false);
void lowerWindow(Window *window, bool nogroup = false);
void raiseWindowRequest(Window *window, NET::RequestSource src = NET::FromApplication, xcb_timestamp_t timestamp = 0);
void raiseWindowRequest(Window *window, NET::RequestSource src = NET::FromApplication, uint32_t timestamp = 0);
#if KWIN_BUILD_X11
void lowerWindowRequest(X11Window *window, NET::RequestSource src, xcb_timestamp_t timestamp);
void restoreSessionStackingOrder(X11Window *window);
#endif
void lowerWindowRequest(Window *window);
void restackWindowUnderActive(Window *window);
void restack(Window *window, Window *under, bool force = false);
void raiseOrLowerWindow(Window *window);
void resetUpdateToolWindowsTimer();
void restoreSessionStackingOrder(X11Window *window);
void updateStackingOrder(bool propagate_new_windows = false);
void forceRestacking();
@ -251,7 +255,9 @@ public:
return m_windows;
}
#if KWIN_BUILD_X11
void stackScreenEdgesUnderOverrideRedirect();
#endif
SessionManager *sessionManager() const;
@ -283,7 +289,6 @@ public:
*/
const QList<Window *> &stackingOrder() const;
QList<Window *> unconstrainedStackingOrder() const;
QList<X11Window *> ensureStackingOrder(const QList<X11Window *> &windows) const;
QList<Window *> ensureStackingOrder(const QList<Window *> &windows) const;
Window *topWindowOnDesktop(VirtualDesktop *desktop, Output *output = nullptr, bool unconstrained = false,
@ -294,6 +299,9 @@ public:
void windowToNextDesktop(Window *window);
void sendWindowToOutput(Window *window, Output *output);
#if KWIN_BUILD_X11
QList<X11Window *> ensureStackingOrder(const QList<X11Window *> &windows) const;
void addManualOverlay(xcb_window_t id)
{
manual_overlays << id;
@ -302,6 +310,7 @@ public:
{
manual_overlays.removeOne(id);
}
#endif
/**
* Shows the menu operations menu for the window and makes it active if
@ -317,9 +326,11 @@ public:
void updateMinimizedOfTransients(Window *);
void updateOnAllDesktopsOfTransients(Window *);
void checkTransients(xcb_window_t w);
#if KWIN_BUILD_X11
void checkTransients(xcb_window_t w);
SessionInfo *takeSessionInfo(X11Window *);
#endif
// D-Bus interface
QString supportInformation() const;
@ -347,8 +358,9 @@ public:
void setShowingDesktop(bool showing, bool animated = true);
bool showingDesktop() const;
void removeX11Window(X11Window *); // Only called from X11Window::destroyWindow() or X11Window::releaseWindow()
void setActiveWindow(Window *window);
#if KWIN_BUILD_X11
void removeX11Window(X11Window *); // Only called from X11Window::destroyWindow() or X11Window::releaseWindow()
Group *findGroup(xcb_window_t leader) const;
void addGroup(Group *group);
void removeGroup(Group *group);
@ -356,11 +368,11 @@ public:
int unconstainedStackingOrderIndex(const X11Window *c) const;
void removeUnmanaged(X11Window *);
bool checkStartupNotification(xcb_window_t w, KStartupInfoId &id, KStartupInfoData &data);
#endif
void removeDeleted(Window *);
void addDeleted(Window *);
bool checkStartupNotification(xcb_window_t w, KStartupInfoId &id, KStartupInfoData &data);
void focusToNull(); // SELI TODO: Public?
void windowShortcutUpdated(Window *window);
@ -521,7 +533,9 @@ public Q_SLOTS:
private Q_SLOTS:
void desktopResized();
#if KWIN_BUILD_X11
void selectWmInputEventMask();
#endif
void slotUpdateToolWindows();
void delayFocus();
void slotReloadConfig();
@ -551,7 +565,9 @@ Q_SIGNALS:
void windowRemoved(KWin::Window *);
void windowActivated(KWin::Window *);
void windowMinimizedChanged(KWin::Window *);
#if KWIN_BUILD_X11
void groupAdded(KWin::Group *);
#endif
void deletedRemoved(KWin::Window *);
void configChanged();
void showingDesktopChanged(bool showing, bool animated);
@ -567,8 +583,6 @@ Q_SIGNALS:
private:
void init();
void initializeX11();
void cleanupX11();
void initShortcuts();
template<typename Slot>
void initShortcut(const QString &actionName, const QString &description, const QKeySequence &shortcut, Slot slot);
@ -577,24 +591,30 @@ private:
void setupWindowShortcut(Window *window);
bool switchWindow(Window *window, Direction direction, QPoint curPos, VirtualDesktop *desktop);
void propagateWindows(bool propagate_new_windows); // Called only from updateStackingOrder
QList<Window *> constrainedStackingOrder();
void raiseWindowWithinApplication(Window *window);
void lowerWindowWithinApplication(Window *window);
bool allowFullClientRaising(const Window *window, xcb_timestamp_t timestamp);
bool allowFullClientRaising(const Window *window, uint32_t timestamp);
void blockStackingUpdates(bool block);
void updateToolWindows(bool also_hide);
void fixPositionAfterCrash(xcb_window_t w, const xcb_get_geometry_reply_t *geom);
void saveOldScreenSizes();
void addToStack(Window *window);
void removeFromStack(Window *window);
#if KWIN_BUILD_X11
void initializeX11();
void cleanupX11();
void propagateWindows(bool propagate_new_windows); // Called only from updateStackingOrder
void fixPositionAfterCrash(xcb_window_t w, const xcb_get_geometry_reply_t *geom);
/// This is the right way to create a new X11 window
X11Window *createX11Window(xcb_window_t windowId, bool is_mapped);
void addX11Window(X11Window *c);
void setupWindowConnections(Window *window);
X11Window *createUnmanaged(xcb_window_t windowId);
void addUnmanaged(X11Window *c);
void updateXStackingOrder();
#endif
void setupWindowConnections(Window *window);
void addWaylandWindow(Window *window);
void removeWaylandWindow(Window *window);
@ -632,7 +652,6 @@ private:
Window *m_activePopupWindow;
int m_initialDesktop;
void updateXStackingOrder();
void updateTabbox();
QList<Output *> m_outputs;
@ -654,7 +673,6 @@ private:
QList<Window *> unconstrained_stacking_order; // Topmost last
QList<Window *> stacking_order; // Topmost last
QList<xcb_window_t> manual_overlays; // Topmost last
bool force_restacking;
QList<Window *> should_get_focus; // Last is most recent
QList<Window *> attention_chain;
@ -664,7 +682,13 @@ private:
QList<Group *> groups;
bool was_user_interaction;
#if KWIN_BUILD_X11
QList<xcb_window_t> manual_overlays; // Topmost last
std::unique_ptr<X11EventFilter> m_wasUserInteractionFilter;
std::unique_ptr<Xcb::Window> m_nullFocus;
std::unique_ptr<X11EventFilter> m_movingClientFilter;
std::unique_ptr<X11EventFilter> m_syncAlarmFilter;
#endif
int block_focus;
@ -686,9 +710,9 @@ private:
QTimer updateToolWindowsTimer;
static Workspace *_self;
#if KWIN_BUILD_X11
std::unique_ptr<KStartupInfo> m_startup;
#endif
QHash<const VirtualDesktop *, QRectF> m_workAreas;
QHash<const VirtualDesktop *, StrutRects> m_restrictedAreas;
QHash<const VirtualDesktop *, QHash<const Output *, QRectF>> m_screenAreas;
@ -701,12 +725,9 @@ private:
int m_setActiveWindowRecursion = 0;
int m_blockStackingUpdates = 0; // When > 0, stacking updates are temporarily disabled
bool m_blockedPropagatingNewWindows; // Propagate also new windows after enabling stacking updates?
std::unique_ptr<Xcb::Window> m_nullFocus;
friend class StackingUpdatesBlocker;
std::unique_ptr<KillWindow> m_windowKiller;
std::unique_ptr<X11EventFilter> m_movingClientFilter;
std::unique_ptr<X11EventFilter> m_syncAlarmFilter;
SessionManager *m_sessionManager;
std::unique_ptr<FocusChain> m_focusChain;
@ -775,6 +796,7 @@ inline Window *Workspace::mostRecentlyActivatedWindow() const
return should_get_focus.count() > 0 ? should_get_focus.last() : m_activeWindow;
}
#if KWIN_BUILD_X11
inline void Workspace::addGroup(Group *group)
{
Q_EMIT groupAdded(group);
@ -785,6 +807,7 @@ inline void Workspace::removeGroup(Group *group)
{
groups.removeAll(group);
}
#endif
inline const QList<Window *> &Workspace::stackingOrder() const
{

View file

@ -5182,6 +5182,388 @@ void X11Window::getSkipCloseAnimation()
readSkipCloseAnimation(property);
}
//********************************************
// Client
//********************************************
/**
* Updates the user time (time of last action in the active window).
* This is called inside kwin for every action with the window
* that qualifies for user interaction (clicking on it, activate it
* externally, etc.).
*/
void X11Window::updateUserTime(xcb_timestamp_t time)
{
// copied in Group::updateUserTime
if (time == XCB_TIME_CURRENT_TIME) {
kwinApp()->updateXTime();
time = xTime();
}
if (time != -1U
&& (m_userTime == XCB_TIME_CURRENT_TIME
|| NET::timestampCompare(time, m_userTime) > 0)) { // time > user_time
m_userTime = time;
shade_below = nullptr; // do not hover re-shade a window after it got interaction
}
group()->updateUserTime(m_userTime);
}
xcb_timestamp_t X11Window::readUserCreationTime() const
{
Xcb::Property prop(false, window(), atoms->kde_net_wm_user_creation_time, XCB_ATOM_CARDINAL, 0, 1);
return prop.value<xcb_timestamp_t>(-1);
}
xcb_timestamp_t X11Window::readUserTimeMapTimestamp(const KStartupInfoId *asn_id, const KStartupInfoData *asn_data,
bool session) const
{
xcb_timestamp_t time = info->userTime();
// qDebug() << "User timestamp, initial:" << time;
//^^ this deadlocks kwin --replace sometimes.
// newer ASN timestamp always replaces user timestamp, unless user timestamp is 0
// helps e.g. with konqy reusing
if (asn_data != nullptr && time != 0) {
if (asn_id->timestamp() != 0
&& (time == -1U || NET::timestampCompare(asn_id->timestamp(), time) > 0)) {
time = asn_id->timestamp();
}
}
qCDebug(KWIN_CORE) << "User timestamp, ASN:" << time;
if (time == -1U) {
// The window doesn't have any timestamp.
// If it's the first window for its application
// (i.e. there's no other window from the same app),
// use the _KDE_NET_WM_USER_CREATION_TIME trick.
// Otherwise, refuse activation of a window
// from already running application if this application
// is not the active one (unless focus stealing prevention is turned off).
X11Window *act = dynamic_cast<X11Window *>(workspace()->mostRecentlyActivatedWindow());
if (act != nullptr && !belongToSameApplication(act, this, SameApplicationCheck::RelaxedForActive)) {
bool first_window = true;
auto sameApplicationActiveHackPredicate = [this](const X11Window *cl) {
// ignore already existing splashes, toolbars, utilities and menus,
// as the app may show those before the main window
return !cl->isSplash() && !cl->isToolbar() && !cl->isUtility() && !cl->isMenu()
&& cl != this && X11Window::belongToSameApplication(cl, this, SameApplicationCheck::RelaxedForActive);
};
if (isTransient()) {
auto clientMainClients = [this]() {
QList<X11Window *> ret;
const auto mcs = mainWindows();
for (auto mc : mcs) {
if (X11Window *c = dynamic_cast<X11Window *>(mc)) {
ret << c;
}
}
return ret;
};
if (act->hasTransient(this, true)) {
; // is transient for currently active window, even though it's not
// the same app (e.g. kcookiejar dialog) -> allow activation
} else if (groupTransient() && findInList<X11Window, X11Window>(clientMainClients(), sameApplicationActiveHackPredicate) == nullptr) {
; // standalone transient
} else {
first_window = false;
}
} else {
#if KWIN_BUILD_X11
if (workspace()->findClient(sameApplicationActiveHackPredicate)) {
first_window = false;
}
#endif
}
// don't refuse if focus stealing prevention is turned off
if (!first_window && rules()->checkFSP(options->focusStealingPreventionLevel()) > 0) {
qCDebug(KWIN_CORE) << "User timestamp, already exists:" << 0;
return 0; // refuse activation
}
}
// Creation time would just mess things up during session startup,
// as possibly many apps are started up at the same time.
// If there's no active window yet, no timestamp will be needed,
// as plain Workspace::allowWindowActivation() will return true
// in such case. And if there's already active window,
// it's better not to activate the new one.
// Unless it was the active window at the time
// of session saving and there was no user interaction yet,
// this check will be done in manage().
if (session) {
return -1U;
}
time = readUserCreationTime();
}
qCDebug(KWIN_CORE) << "User timestamp, final:" << this << ":" << time;
return time;
}
xcb_timestamp_t X11Window::userTime() const
{
xcb_timestamp_t time = m_userTime;
if (time == 0) { // doesn't want focus after showing
return 0;
}
Q_ASSERT(group() != nullptr);
if (time == -1U
|| (group()->userTime() != -1U
&& NET::timestampCompare(group()->userTime(), time) > 0)) {
time = group()->userTime();
}
return time;
}
void X11Window::doSetActive()
{
updateUrgency(); // demand attention again if it's still urgent
info->setState(isActive() ? NET::Focused : NET::States(), NET::Focused);
}
void X11Window::startupIdChanged()
{
KStartupInfoId asn_id;
KStartupInfoData asn_data;
bool asn_valid = workspace()->checkStartupNotification(window(), asn_id, asn_data);
if (!asn_valid) {
return;
}
// If the ASN contains desktop, move it to the desktop, otherwise move it to the current
// desktop (since the new ASN should make the window act like if it's a new application
// launched). However don't affect the window's desktop if it's set to be on all desktops.
if (asn_data.desktop() != 0 && !isOnAllDesktops()) {
if (asn_data.desktop() == -1) {
workspace()->sendWindowToDesktops(this, {}, true);
} else {
if (VirtualDesktop *desktop = VirtualDesktopManager::self()->desktopForX11Id(asn_data.desktop())) {
workspace()->sendWindowToDesktops(this, {desktop}, true);
}
}
}
if (asn_data.xinerama() != -1) {
Output *output = workspace()->xineramaIndexToOutput(asn_data.xinerama());
if (output) {
workspace()->sendWindowToOutput(this, output);
}
}
const xcb_timestamp_t timestamp = asn_id.timestamp();
if (timestamp != 0) {
bool activate = allowWindowActivation(timestamp);
if (activate) {
workspace()->activateWindow(this);
} else {
demandAttention();
}
}
}
void X11Window::updateUrgency()
{
if (info->urgency()) {
demandAttention();
}
}
namespace FSP
{
enum Level {
None = 0,
Low,
Medium,
High,
Extreme,
};
}
// focus_in -> the window got FocusIn event
bool X11Window::allowWindowActivation(xcb_timestamp_t time, bool focus_in)
{
auto window = this;
// options->focusStealingPreventionLevel :
// 0 - none - old KWin behaviour, new windows always get focus
// 1 - low - focus stealing prevention is applied normally, when unsure, activation is allowed
// 2 - normal - focus stealing prevention is applied normally, when unsure, activation is not allowed,
// this is the default
// 3 - high - new window gets focus only if it belongs to the active application,
// or when no window is currently active
// 4 - extreme - no window gets focus without user intervention
if (time == -1U) {
time = window->userTime();
}
const FSP::Level level = (FSP::Level)window->rules()->checkFSP(options->focusStealingPreventionLevel());
if (workspace()->sessionManager()->state() == SessionState::Saving && level <= FSP::Medium) { // <= normal
return true;
}
Window *ac = workspace()->mostRecentlyActivatedWindow();
if (focus_in) {
if (workspace()->inShouldGetFocus(window)) {
return true; // FocusIn was result of KWin's action
}
// Before getting FocusIn, the active Client already
// got FocusOut, and therefore got deactivated.
ac = workspace()->lastActiveWindow();
}
if (time == 0) { // explicitly asked not to get focus
if (!window->rules()->checkAcceptFocus(false)) {
return false;
}
}
const FSP::Level protection = (FSP::Level)(ac ? ac->rules()->checkFPP(2) : FSP::None);
// stealing is unconditionally allowed (NETWM behavior)
if (level == FSP::None || protection == FSP::None) {
return true;
}
// The active window "grabs" the focus or stealing is generally forbidden
if (level == FSP::Extreme || protection == FSP::Extreme) {
return false;
}
// No active window, it's ok to pass focus
// NOTICE that extreme protection needs to be handled before to allow protection on unmanged windows
if (ac == nullptr || ac->isDesktop()) {
qCDebug(KWIN_CORE) << "Activation: No window active, allowing";
return true; // no active window -> always allow
}
// TODO window urgency -> return true?
// Unconditionally allow intra-window passing around for lower stealing protections
// unless the active window has High interest
if (Window::belongToSameApplication(window, ac, Window::SameApplicationCheck::RelaxedForActive) && protection < FSP::High) {
qCDebug(KWIN_CORE) << "Activation: Belongs to active application";
return true;
}
// High FPS, not intr-window change. Only allow if the active window has only minor interest
if (level > FSP::Medium && protection > FSP::Low) {
return false;
}
if (time == -1U) { // no time known
qCDebug(KWIN_CORE) << "Activation: No timestamp at all";
// Only allow for Low protection unless active window has High interest in focus
if (level < FSP::Medium && protection < FSP::High) {
return true;
}
// no timestamp at all, don't activate - because there's also creation timestamp
// done on CreateNotify, this case should happen only in case application
// maps again already used window, i.e. this won't happen after app startup
return false;
}
// Low or medium FSP, usertime comparism is possible
const xcb_timestamp_t user_time = ac->userTime();
qCDebug(KWIN_CORE) << "Activation, compared:" << window << ":" << time << ":" << user_time
<< ":" << (NET::timestampCompare(time, user_time) >= 0);
return NET::timestampCompare(time, user_time) >= 0; // time >= user_time
}
void X11Window::restackWindow(xcb_window_t above, int detail, NET::RequestSource src, xcb_timestamp_t timestamp, bool send_event)
{
X11Window *other = nullptr;
if (detail == XCB_STACK_MODE_OPPOSITE) {
other = workspace()->findClient(Predicate::WindowMatch, above);
if (!other) {
workspace()->raiseOrLowerWindow(this);
return;
}
auto it = workspace()->stackingOrder().constBegin(),
end = workspace()->stackingOrder().constEnd();
while (it != end) {
if (*it == this) {
detail = XCB_STACK_MODE_ABOVE;
break;
} else if (*it == other) {
detail = XCB_STACK_MODE_BELOW;
break;
}
++it;
}
} else if (detail == XCB_STACK_MODE_TOP_IF) {
other = workspace()->findClient(Predicate::WindowMatch, above);
if (other && other->frameGeometry().intersects(frameGeometry())) {
workspace()->raiseWindowRequest(this, src, timestamp);
}
return;
} else if (detail == XCB_STACK_MODE_BOTTOM_IF) {
other = workspace()->findClient(Predicate::WindowMatch, above);
if (other && other->frameGeometry().intersects(frameGeometry())) {
workspace()->lowerWindowRequest(this, src, timestamp);
}
return;
}
if (!other) {
other = workspace()->findClient(Predicate::WindowMatch, above);
}
if (other && detail == XCB_STACK_MODE_ABOVE) {
auto it = workspace()->stackingOrder().constEnd(),
begin = workspace()->stackingOrder().constBegin();
while (--it != begin) {
if (*it == other) { // the other one is top on stack
it = begin; // invalidate
src = NET::FromTool; // force
break;
}
X11Window *window = qobject_cast<X11Window *>(*it);
if (!window || !((*it)->isNormalWindow() && window->isShown() && (*it)->isOnCurrentDesktop() && (*it)->isOnCurrentActivity() && (*it)->isOnOutput(output()))) {
continue; // irrelevant windows
}
if (*(it - 1) == other) {
break; // "it" is the one above the target one, stack below "it"
}
}
if (it != begin && (*(it - 1) == other)) {
other = qobject_cast<X11Window *>(*it);
} else {
other = nullptr;
}
}
if (other) {
workspace()->restack(this, other);
} else if (detail == XCB_STACK_MODE_BELOW) {
workspace()->lowerWindowRequest(this, src, timestamp);
} else if (detail == XCB_STACK_MODE_ABOVE) {
workspace()->raiseWindowRequest(this, src, timestamp);
}
if (send_event) {
sendSyntheticConfigureNotify();
}
}
bool X11Window::belongsToDesktop() const
{
const auto members = group()->members();
for (const X11Window *window : members) {
if (window->isDesktop()) {
return true;
}
}
return false;
}
void X11Window::setShortcutInternal()
{
updateCaption();
#if 0
workspace()->windowShortcutUpdated(this);
#else
// Workaround for kwin<->kglobalaccel deadlock, when KWin has X grab and the kded
// kglobalaccel module tries to create the key grab. KWin should preferably grab
// they keys itself anyway :(.
QTimer::singleShot(0, this, std::bind(&Workspace::windowShortcutUpdated, workspace(), this));
#endif
}
} // namespace
#include "moc_x11window.cpp"

View file

@ -9,6 +9,11 @@
*/
#pragma once
#include "config-kwin.h"
#if !KWIN_BUILD_X11
#error Do not include on non-X11 builds
#endif
// kwin
#include "scene/decorationitem.h"

View file

@ -9,6 +9,12 @@
*/
#pragma once
#include "config-kwin.h"
#if !KWIN_BUILD_X11
#error Do not include on non-X11 builds
#endif
#include <memory>
#include "xwayland_interface.h"

View file

@ -1,18 +1,20 @@
set(normalhintsbasesizetest_SRCS normalhintsbasesizetest.cpp)
add_executable(normalhintsbasesizetest ${normalhintsbasesizetest_SRCS})
target_link_libraries(normalhintsbasesizetest XCB::XCB XCB::ICCCM KF6::WindowSystem)
if(KWIN_BUILD_X11)
set(normalhintsbasesizetest_SRCS normalhintsbasesizetest.cpp)
add_executable(normalhintsbasesizetest ${normalhintsbasesizetest_SRCS})
target_link_libraries(normalhintsbasesizetest XCB::XCB XCB::ICCCM KF6::WindowSystem)
# next target
set(screenedgeshowtest_SRCS screenedgeshowtest.cpp)
add_executable(screenedgeshowtest ${screenedgeshowtest_SRCS})
target_link_libraries(screenedgeshowtest Qt::GuiPrivate Qt::Widgets KF6::ConfigCore KF6::WindowSystem Plasma::KWaylandClient ${XCB_XCB_LIBRARY})
# next target
set(screenedgeshowtest_SRCS screenedgeshowtest.cpp)
add_executable(screenedgeshowtest ${screenedgeshowtest_SRCS})
target_link_libraries(screenedgeshowtest Qt::GuiPrivate Qt::Widgets KF6::ConfigCore KF6::WindowSystem Plasma::KWaylandClient ${XCB_XCB_LIBRARY})
add_executable(x11shadowreader x11shadowreader.cpp)
target_link_libraries(x11shadowreader XCB::XCB Qt::GuiPrivate Qt::Widgets KF6::ConfigCore KF6::WindowSystem)
add_executable(x11shadowreader x11shadowreader.cpp)
target_link_libraries(x11shadowreader XCB::XCB Qt::GuiPrivate Qt::Widgets KF6::ConfigCore KF6::WindowSystem)
add_executable(pointerconstraints pointerconstraintstest.cpp)
add_definitions(-DDIR="${CMAKE_CURRENT_SOURCE_DIR}")
target_link_libraries(pointerconstraints XCB::XCB Qt::Gui Qt::Quick Plasma::KWaylandClient)
add_executable(pointerconstraints pointerconstraintstest.cpp)
add_definitions(-DDIR="${CMAKE_CURRENT_SOURCE_DIR}")
target_link_libraries(pointerconstraints XCB::XCB Qt::Gui Qt::Quick Plasma::KWaylandClient)
endif()
add_executable(pointergestures pointergesturestest.cpp)
add_definitions(-DDIR="${CMAKE_CURRENT_SOURCE_DIR}")