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,243 @@
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 2008 Fredrik Höglund <fredrik@kde.org>
SPDX-FileCopyrightText: 2008 Konstantin Heil <konst.heil@stud.uni-heidelberg.de>
SPDX-FileCopyrightText: 2009 Peter Penz <peter.penz@gmx.at>
SPDX-FileCopyrightText: 2017 Elvis Angelaccio <elvis.angelaccio@kde.org>
SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "ktooltipwidget.h"
#include <QPaintEvent>
#include <QScreen>
#include <QStyleOptionFrame>
#include <QStylePainter>
#include <QTimer>
#include <QVBoxLayout>
#include <QWindow>
class KToolTipWidgetPrivate
{
public:
KToolTipWidgetPrivate(KToolTipWidget *parent)
: q(parent)
{
}
void init();
void addWidget(QWidget *widget);
void removeWidget();
void show(const QPoint &pos, QWindow *transientParent);
void storeParent();
void restoreParent();
QPoint centerBelow(const QRect &rect, QScreen *screen) const;
KToolTipWidget *const q;
QTimer hideTimer;
QVBoxLayout *layout = nullptr;
QWidget *content = nullptr;
QWidget *contentParent = nullptr;
};
void KToolTipWidgetPrivate::init()
{
layout = new QVBoxLayout(q);
hideTimer.setSingleShot(true);
hideTimer.setInterval(500);
QObject::connect(&hideTimer, &QTimer::timeout, q, &QWidget::hide);
q->setAttribute(Qt::WA_TranslucentBackground);
q->setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint);
}
void KToolTipWidgetPrivate::addWidget(QWidget *widget)
{
removeWidget();
content = widget;
storeParent();
layout->addWidget(content);
QObject::connect(content, &QWidget::destroyed, q, &QWidget::hide);
}
void KToolTipWidgetPrivate::removeWidget()
{
layout->removeWidget(content);
restoreParent();
}
void KToolTipWidgetPrivate::show(const QPoint &pos, QWindow *transientParent)
{
if (pos.isNull()) {
return;
}
q->move(pos);
q->createWinId();
q->windowHandle()->setProperty("ENABLE_BLUR_BEHIND_HINT", true);
q->windowHandle()->setTransientParent(transientParent);
QObject::connect(transientParent, &QWindow::activeChanged, q, &QWidget::hide);
q->show();
}
void KToolTipWidgetPrivate::storeParent()
{
if (!content) {
return;
}
contentParent = qobject_cast<QWidget *>(content->parent());
}
void KToolTipWidgetPrivate::restoreParent()
{
if (!content || !contentParent) {
return;
}
content->setParent(contentParent);
}
QPoint KToolTipWidgetPrivate::centerBelow(const QRect &rect, QScreen *screen) const
{
// It must be assured that:
// - the content is fully visible
// - the content is not drawn inside rect
const QSize size = q->sizeHint();
const int margin = q->style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth);
const QRect screenGeometry = screen->geometry();
const bool hasRoomToLeft = (rect.left() - size.width() - margin >= screenGeometry.left());
const bool hasRoomToRight = (rect.right() + size.width() + margin <= screenGeometry.right());
const bool hasRoomAbove = (rect.top() - size.height() - margin >= screenGeometry.top());
const bool hasRoomBelow = (rect.bottom() + size.height() + margin <= screenGeometry.bottom());
if (!hasRoomAbove && !hasRoomBelow && !hasRoomToLeft && !hasRoomToRight) {
return QPoint();
}
int x = 0;
int y = 0;
if (hasRoomBelow || hasRoomAbove) {
x = qMax(screenGeometry.left(), rect.center().x() - size.width() / 2);
if (x + size.width() >= screenGeometry.right()) {
x = screenGeometry.right() - size.width() + 1;
}
Q_ASSERT(x >= 0);
if (hasRoomBelow) {
y = rect.bottom() + margin;
} else {
y = rect.top() - size.height() - margin + 1;
}
} else {
Q_ASSERT(hasRoomToLeft || hasRoomToRight);
if (hasRoomToRight) {
x = rect.right() + margin;
} else {
x = rect.left() - size.width() - margin + 1;
}
// Put the tooltip at the bottom of the screen. The x-coordinate has already
// been adjusted, so that no overlapping with rect occurs.
y = screenGeometry.bottom() - size.height() + 1;
}
return QPoint(x, y);
}
KToolTipWidget::KToolTipWidget(QWidget *parent)
: QWidget(parent)
, d(new KToolTipWidgetPrivate(this))
{
d->init();
}
KToolTipWidget::~KToolTipWidget()
{
d->restoreParent();
}
void KToolTipWidget::showAt(const QPoint &pos, QWidget *content, QWindow *transientParent)
{
d->addWidget(content);
d->show(pos, transientParent);
}
void KToolTipWidget::showBelow(const QRect &rect, QWidget *content, QWindow *transientParent)
{
d->addWidget(content);
const auto contentMargins = layout()->contentsMargins();
const QSize screenSize = transientParent->screen()->geometry().size();
content->setMaximumSize(screenSize.shrunkBy(contentMargins));
d->show(d->centerBelow(rect, transientParent->screen()), transientParent);
}
int KToolTipWidget::hideDelay() const
{
return d->hideTimer.interval();
}
void KToolTipWidget::hideLater()
{
if (!isVisible()) {
return;
}
if (hideDelay() > 0) {
d->hideTimer.start();
} else {
hide();
}
}
void KToolTipWidget::setHideDelay(int delay)
{
d->hideTimer.setInterval(delay);
}
void KToolTipWidget::enterEvent(QEnterEvent *)
{
// Ignore hide delay and leave tooltip visible.
if (hideDelay() > 0) {
d->hideTimer.stop();
} else {
hide();
}
}
void KToolTipWidget::hideEvent(QHideEvent *)
{
d->removeWidget();
QObject::disconnect(windowHandle()->transientParent(), &QWindow::activeChanged, this, &QWidget::hide);
// Give time to the content widget to get his own hide event.
QTimer::singleShot(0, this, &KToolTipWidget::hidden);
}
void KToolTipWidget::leaveEvent(QEvent *)
{
// Don't bother starting the hide timer, we are done.
hide();
}
void KToolTipWidget::paintEvent(QPaintEvent *event)
{
QStylePainter painter(this);
painter.setClipRegion(event->region());
QStyleOptionFrame option;
option.initFrom(this);
painter.drawPrimitive(QStyle::PE_PanelTipLabel, option);
painter.end();
QWidget::paintEvent(event);
}
#include "moc_ktooltipwidget.cpp"