Advance Wayland and KDE package bring-up

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-04-14 10:51:06 +01:00
parent 51f3c21121
commit cf12defd28
15214 changed files with 20594243 additions and 269 deletions
@@ -0,0 +1,35 @@
remove_definitions(-DQT_NO_CAST_FROM_ASCII)
remove_definitions(-DQT_NO_CAST_TO_ASCII)
include(ECMMarkAsTest)
find_package(Qt6 ${REQUIRED_QT_VERSION} CONFIG REQUIRED Test Widgets)
macro(kwindowsystem_executable_tests)
foreach(_testname ${ARGN})
add_executable(${_testname} ${_testname}.cpp)
target_link_libraries(${_testname} Qt6::Test Qt6::Widgets KF6::WindowSystem)
ecm_mark_as_test(${_testname})
endforeach(_testname)
endmacro()
kwindowsystem_executable_tests(
blurbehindtest
backgroundcontrasttest
)
if(KWINDOWSYSTEM_X11)
kwindowsystem_executable_tests(
icontest
createpixmapfromhandletest
setmainwindowtest
)
target_link_libraries(icontest Qt6::GuiPrivate)
endif()
if(KWINDOWSYSTEM_WAYLAND)
kwindowsystem_executable_tests(
kwaylandextrastest
activationtest
)
endif()
@@ -0,0 +1,48 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2024 Nicolas Fella <nicolas.fella@gmx.de>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include <kwindowsystem.h>
#include <QApplication>
#include <QLayout>
#include <QMainWindow>
#include <QPushButton>
#include <kwaylandextras.h>
class MainWindow : public QMainWindow
{
public:
MainWindow()
: QMainWindow()
{
QMainWindow *otherWindow = new QMainWindow(this);
otherWindow->show();
otherWindow->setWindowState(Qt::WindowMinimized);
QPushButton *pushButton = new QPushButton(otherWindow);
pushButton->setText("Raise other");
layout()->addWidget(pushButton);
connect(pushButton, &QPushButton::clicked, this, [this] {
KWaylandExtras::requestXdgActivationToken(windowHandle(), KWaylandExtras::lastInputSerial(windowHandle()), QString());
});
connect(KWaylandExtras::self(), &KWaylandExtras::xdgActivationTokenArrived, this, [otherWindow](int /*serial*/, const QString &token) {
KWindowSystem::setCurrentXdgActivationToken(token);
KWindowSystem::activateWindow(otherWindow->windowHandle());
});
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
@@ -0,0 +1,237 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2013 Nicolás Alvarez <nicolas.alvarez@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include <optional>
#include <QApplication>
#include <QColorDialog>
#include <QDebug>
#include <QPaintEvent>
#include <QPainter>
#include <QPushButton>
#include <QScopeGuard>
#include <QSlider>
#include <QVBoxLayout>
#include <QWidget>
#include <kwindoweffects.h>
class ContrastTestWindow : public QWidget
{
public:
ContrastTestWindow();
void resizeEvent(QResizeEvent *) override;
private:
QPushButton *m_btnNothing;
QPushButton *m_btnFullWindow;
QPushButton *m_btnRect;
QPushButton *m_btnEllipse;
QPushButton *m_blur;
bool m_doBlur;
QPushButton *m_bg;
QColor m_bgColour;
QSlider *m_contSlider;
QSlider *m_intSlider;
QSlider *m_satSlider;
QWidget *m_area;
qreal m_contrast;
qreal m_intensity;
qreal m_saturation;
enum { Nothing, FullWindow, Rect, Ellipse } m_state;
void disableContrast();
void enableContrast();
void enableContrastRect();
void enableContrastEllipse();
void updateContrast(int contrast);
void updateIntensity(int contrast);
void updateSaturation(int contrast);
void update();
void paintEvent(QPaintEvent *event) override
{
Q_UNUSED(event)
QPainter p(this);
p.setPen(Qt::transparent);
p.setBrush(m_bgColour);
p.drawRect(this->rect());
QWidget::paintEvent(event);
}
};
ContrastTestWindow::ContrastTestWindow()
{
m_state = Nothing;
m_contrast = 1;
m_intensity = 1;
m_saturation = 1;
m_bgColour = Qt::transparent;
setAttribute(Qt::WA_TranslucentBackground);
setAttribute(Qt::WA_NoSystemBackground, true);
m_btnNothing = new QPushButton("Nothing");
m_btnFullWindow = new QPushButton("Full window");
m_btnRect = new QPushButton("Rectangle");
m_btnEllipse = new QPushButton("Ellipse");
m_blur = new QPushButton("Enable Blur");
m_blur->setCheckable(true);
m_bg = new QPushButton("Set Background Colour...");
connect(m_bg, &QPushButton::pressed, this, [this]() {
m_bgColour = QColorDialog::getColor(Qt::white, nullptr, "pick colour", QColorDialog::ShowAlphaChannel);
repaint();
});
connect(m_blur, &QPushButton::toggled, this, [this](bool checked) {
m_blur->setText(checked ? "Disable Blur" : "Enable Blur");
m_doBlur = checked;
update();
});
m_contSlider = new QSlider();
m_contSlider->setMaximum(200);
m_contSlider->setValue(100);
m_contSlider->setOrientation(Qt::Horizontal);
m_intSlider = new QSlider();
m_intSlider->setMaximum(200);
m_intSlider->setValue(100);
m_intSlider->setOrientation(Qt::Horizontal);
m_satSlider = new QSlider();
m_satSlider->setMaximum(200);
m_satSlider->setValue(100);
m_satSlider->setOrientation(Qt::Horizontal);
m_area = new QWidget;
m_area->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
connect(m_btnNothing, &QPushButton::clicked, this, &ContrastTestWindow::disableContrast);
connect(m_btnFullWindow, &QPushButton::clicked, this, &ContrastTestWindow::enableContrast);
connect(m_btnRect, &QPushButton::clicked, this, &ContrastTestWindow::enableContrastRect);
connect(m_btnEllipse, &QPushButton::clicked, this, &ContrastTestWindow::enableContrastEllipse);
connect(m_contSlider, &QSlider::valueChanged, this, &ContrastTestWindow::updateContrast);
connect(m_intSlider, &QSlider::valueChanged, this, &ContrastTestWindow::updateIntensity);
connect(m_satSlider, &QSlider::valueChanged, this, &ContrastTestWindow::updateSaturation);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(m_btnNothing);
layout->addWidget(m_btnFullWindow);
layout->addWidget(m_btnRect);
layout->addWidget(m_btnEllipse);
layout->addWidget(m_contSlider);
layout->addWidget(m_intSlider);
layout->addWidget(m_satSlider);
layout->addWidget(m_area);
layout->addWidget(m_blur);
layout->addWidget(m_bg);
winId(); // force creation of the associated window
}
void ContrastTestWindow::update()
{
const auto s = qScopeGuard([this]() {
repaint();
});
if (m_state == Nothing) {
KWindowEffects::enableBackgroundContrast(windowHandle(), false);
KWindowEffects::enableBlurBehind(windowHandle(), false);
}
auto region = QRegion();
switch (m_state) {
case Nothing:
case FullWindow:
break;
case Rect:
region = m_area->geometry();
break;
case Ellipse:
region = QRegion(m_area->geometry(), QRegion::Ellipse);
break;
}
KWindowEffects::enableBlurBehind(windowHandle(), m_doBlur, region);
KWindowEffects::enableBackgroundContrast(windowHandle(), true, m_contrast, m_intensity, m_saturation, region);
repaint();
}
void ContrastTestWindow::disableContrast()
{
m_state = Nothing;
update();
}
void ContrastTestWindow::enableContrast()
{
m_state = FullWindow;
update();
}
void ContrastTestWindow::enableContrastRect()
{
m_state = Rect;
update();
}
void ContrastTestWindow::enableContrastEllipse()
{
m_state = Ellipse;
update();
}
void ContrastTestWindow::updateContrast(int contrast)
{
m_contrast = (qreal)contrast / 100;
update();
}
void ContrastTestWindow::updateIntensity(int contrast)
{
m_intensity = (qreal)contrast / 100;
update();
}
void ContrastTestWindow::updateSaturation(int contrast)
{
m_saturation = (qreal)contrast / 100;
update();
}
void ContrastTestWindow::resizeEvent(QResizeEvent *)
{
update();
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
ContrastTestWindow wnd;
wnd.show();
return app.exec();
}
@@ -0,0 +1,122 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2013 Nicolás Alvarez <nicolas.alvarez@gmail.com>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include <QApplication>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <kwindoweffects.h>
class BlurTestWindow : public QWidget
{
public:
BlurTestWindow();
void resizeEvent(QResizeEvent *) override;
private:
QPushButton *m_btnNothing;
QPushButton *m_btnFullWindow;
QPushButton *m_btnRect;
QPushButton *m_btnEllipse;
QWidget *m_area;
enum { Nothing, FullWindow, Rect, Ellipse } m_state;
void setWindowAlpha(int alpha);
void disableBlur();
void enableBlur();
void enableBlurRect();
void enableBlurEllipse();
};
BlurTestWindow::BlurTestWindow()
{
m_state = Nothing;
setAttribute(Qt::WA_TranslucentBackground);
setAttribute(Qt::WA_NoSystemBackground, false);
setWindowAlpha(192);
m_btnNothing = new QPushButton("Nothing");
m_btnFullWindow = new QPushButton("Full window");
m_btnRect = new QPushButton("Rectangle");
m_btnEllipse = new QPushButton("Ellipse");
m_area = new QWidget;
m_area->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
connect(m_btnNothing, &QPushButton::clicked, this, &BlurTestWindow::disableBlur);
connect(m_btnFullWindow, &QPushButton::clicked, this, &BlurTestWindow::enableBlur);
connect(m_btnRect, &QPushButton::clicked, this, &BlurTestWindow::enableBlurRect);
connect(m_btnEllipse, &QPushButton::clicked, this, &BlurTestWindow::enableBlurEllipse);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(m_btnNothing);
layout->addWidget(m_btnFullWindow);
layout->addWidget(m_btnRect);
layout->addWidget(m_btnEllipse);
layout->addWidget(m_area);
winId(); // force creation of the associated window
}
void BlurTestWindow::disableBlur()
{
m_state = Nothing;
KWindowEffects::enableBlurBehind(windowHandle(), false);
repaint();
}
void BlurTestWindow::enableBlur()
{
m_state = FullWindow;
KWindowEffects::enableBlurBehind(windowHandle(), true);
repaint();
}
void BlurTestWindow::enableBlurRect()
{
m_state = Rect;
QRegion rgn(m_area->geometry());
KWindowEffects::enableBlurBehind(windowHandle(), true, rgn);
repaint();
}
void BlurTestWindow::enableBlurEllipse()
{
m_state = Ellipse;
QRegion rgn(m_area->geometry(), QRegion::Ellipse);
KWindowEffects::enableBlurBehind(windowHandle(), true, rgn);
repaint();
}
void BlurTestWindow::resizeEvent(QResizeEvent *)
{
if (m_state == Rect) {
enableBlurRect();
} else if (m_state == Ellipse) {
enableBlurEllipse();
}
}
void BlurTestWindow::setWindowAlpha(int alpha)
{
QPalette pal = this->palette();
QColor windowColor = pal.color(QPalette::Window);
windowColor.setAlpha(alpha);
pal.setColor(QPalette::Window, windowColor);
this->setPalette(pal);
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
BlurTestWindow wnd;
wnd.show();
return app.exec();
}
@@ -0,0 +1,26 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include <QApplication>
#include <QCommandLineParser>
#include <QLabel>
#include <kx11extras.h>
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QCommandLineParser parser;
parser.addPositionalArgument(QStringLiteral("WId"), QStringLiteral("window id for the window to take the icon from"), QStringLiteral("[WId]"));
parser.addHelpOption();
parser.process(app);
QLabel label;
label.setMinimumSize(250, 250);
label.show();
QString wId = parser.positionalArguments().first();
label.setPixmap(KX11Extras::icon(wId.toULongLong(nullptr, 0), 250, 250, false, KX11Extras::WMHints));
return app.exec();
}
@@ -0,0 +1,95 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "../src/platforms/xcb/netwm.h"
#include <QApplication>
#include <QCommandLineParser>
#include <QHBoxLayout>
#include <QIcon>
#include <QLabel>
#include <QVBoxLayout>
#include <private/qtx11extras_p.h>
#include <kwindowsystem.h>
#include <kx11extras.h>
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QCommandLineParser parser;
parser.addPositionalArgument(QStringLiteral("WId"), QStringLiteral("window id for the window to take the icon from"), QStringLiteral("[WId]"));
parser.addHelpOption();
parser.process(app);
QWidget window;
QVBoxLayout *vbox = new QVBoxLayout(&window);
bool ok = false;
qulonglong id = parser.positionalArguments().first().toULongLong(&ok);
if (!ok) {
// try hex
id = parser.positionalArguments().first().toULongLong(&ok, 16);
}
if (!ok) {
return 1;
}
NETWinInfo info(QX11Info::connection(), id, QX11Info::appRootWindow(), NET::WMIcon, NET::WM2WindowClass | NET::WM2IconPixmap);
auto addIcons = [&window, vbox, &id, &info](const QString &name, int flag) {
QLabel *title = new QLabel(name, &window);
vbox->addWidget(title);
QIcon icons;
if (flag & KX11Extras::NETWM) {
const int *iconSizes = info.iconSizes();
int index = 0;
while (iconSizes[index] != 0 && iconSizes[index + 1] != 0) {
const int width = iconSizes[index++];
const int height = iconSizes[index++];
NETIcon ni = info.icon(width, height);
if (ni.data) {
QImage img((uchar *)ni.data, (int)ni.size.width, (int)ni.size.height, QImage::Format_ARGB32);
if (!img.isNull()) {
icons.addPixmap(QPixmap::fromImage(img));
}
}
}
}
if (flag & KX11Extras::WMHints) {
icons.addPixmap(KX11Extras::icon(id, 0, 0, false, KX11Extras::WMHints, &info));
}
if (flag & KX11Extras::ClassHint) {
icons = QIcon::fromTheme(QString::fromUtf8(info.windowClassClass()).toLower());
}
if (flag & KX11Extras::XApp) {
icons = QIcon::fromTheme(QLatin1String("xorg"));
}
if (icons.isNull()) {
return;
}
QHBoxLayout *layout = new QHBoxLayout();
const auto sizes = icons.availableSizes();
for (auto it = sizes.begin(); it != sizes.end(); ++it) {
const QSize &s = *it;
QVBoxLayout *v = new QVBoxLayout();
QLabel *l = new QLabel(QStringLiteral("%1/%2").arg(s.width()).arg(s.height()), &window);
v->addWidget(l);
QLabel *p = new QLabel(&window);
p->setPixmap(icons.pixmap(s));
v->addWidget(p);
layout->addLayout(v);
}
vbox->addLayout(layout);
};
addIcons(QStringLiteral("NetWM"), KX11Extras::NETWM);
addIcons(QStringLiteral("WMHints"), KX11Extras::WMHints);
addIcons(QStringLiteral("ClassHint"), KX11Extras::ClassHint);
addIcons(QStringLiteral("XApp"), KX11Extras::XApp);
window.show();
return app.exec();
}
@@ -0,0 +1,125 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2023 Nicolas Fella <nicolas.fella@gmx.de>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include <kwindowsystem.h>
#include <QApplication>
#include <QDialog>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <kwaylandextras.h>
class Window : public QWidget
{
public:
Window();
private:
void updateSerial();
void requestToken();
void exportWindow();
void unexportWindow();
void setExportedHandle(const QString &handle);
QLabel *m_serialLabel;
QLabel *m_tokenLabel;
QLabel *m_exportedLabel;
};
Window::Window()
{
QPushButton *serialButton = new QPushButton("Update serial");
connect(serialButton, &QPushButton::clicked, this, &Window::updateSerial);
QPushButton *tokenButton = new QPushButton("Request token");
connect(tokenButton, &QPushButton::clicked, this, &Window::requestToken);
m_serialLabel = new QLabel;
m_serialLabel->setText("Last input serial: " + QString::number(KWaylandExtras::self()->lastInputSerial(windowHandle())));
m_tokenLabel = new QLabel;
m_tokenLabel->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
m_tokenLabel->setText("XDG actvation token:");
QHBoxLayout *exportLayout = new QHBoxLayout;
QPushButton *exportButton = new QPushButton("Export window");
connect(exportButton, &QPushButton::clicked, this, &Window::exportWindow);
QPushButton *unexportButton = new QPushButton("Unexport window");
connect(unexportButton, &QPushButton::clicked, this, &Window::unexportWindow);
m_exportedLabel = new QLabel;
m_exportedLabel->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
setExportedHandle(QString());
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(serialButton);
layout->addWidget(m_serialLabel);
layout->addWidget(tokenButton);
layout->addWidget(m_tokenLabel);
exportLayout->addWidget(exportButton);
exportLayout->addWidget(unexportButton);
layout->addLayout(exportLayout);
layout->addWidget(m_exportedLabel);
}
void Window::updateSerial()
{
m_serialLabel->setText("Last input serial: " + QString::number(KWaylandExtras::self()->lastInputSerial(windowHandle())));
}
void Window::requestToken()
{
connect(
KWaylandExtras::self(),
&KWaylandExtras::xdgActivationTokenArrived,
this,
[this](int /*serial*/, const QString &token) {
m_tokenLabel->setText("XDG actvation token: " + token);
},
Qt::SingleShotConnection);
KWaylandExtras::requestXdgActivationToken(windowHandle(), KWaylandExtras::self()->lastInputSerial(windowHandle()), QString());
}
void Window::exportWindow()
{
connect(
KWaylandExtras::self(),
&KWaylandExtras::windowExported,
this,
[this](QWindow *window, const QString &handle) {
Q_UNUSED(window);
setExportedHandle(handle);
},
Qt::SingleShotConnection);
KWaylandExtras::exportWindow(windowHandle());
}
void Window::unexportWindow()
{
KWaylandExtras::unexportWindow(windowHandle());
setExportedHandle(QString());
}
void Window::setExportedHandle(const QString &handle)
{
m_exportedLabel->setText("XDG foreign handle: " + handle);
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
Window window;
window.show();
return app.exec();
}
@@ -0,0 +1,76 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2013 Aurélien Gâteau <agateau@kde.org>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include <kwindowsystem.h>
#include <QApplication>
#include <QDialog>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include "kx11extras.h"
class Window : public QWidget
{
public:
Window();
private:
void showWindow();
QLabel *m_label;
};
Window::Window()
{
QPushButton *button = new QPushButton("Start Test");
connect(button, &QPushButton::clicked, this, &Window::showWindow);
m_label = new QLabel;
m_label->setWordWrap(true);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(button);
layout->addWidget(m_label);
setMinimumSize(200, 150);
}
void Window::showWindow()
{
// Wait for user to select another window
m_label->setText("Click on another window to show a dialog on it");
WId us = winId();
while (KX11Extras::activeWindow() == us) {
QApplication::processEvents();
}
// Get the id of the selected window
WId id = KX11Extras::activeWindow();
m_label->setText(QString("Showing dialog on window with id: %1.").arg(id));
// Create test dialog
QDialog *dialog = new QDialog;
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
QHBoxLayout *layout = new QHBoxLayout(dialog);
layout->addWidget(new QLabel("Test Dialog.\nYou should not be able to bring the parent window on top of me."));
// Show it
dialog->setAttribute(Qt::WA_NativeWindow, true);
KWindowSystem::setMainWindow(dialog->windowHandle(), id);
dialog->exec();
m_label->setText(QString());
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
Window window;
window.show();
return app.exec();
}