10#include <KDecoration2/DecoratedClient>
11#include <KDecoration2/Decoration>
12#include <KDecoration2/DecorationSettings>
13#include <KDecoration2/DecorationShadow>
14#include <QCoreApplication>
30 : QQuickPaintedItem(parent)
31 , m_decoration(nullptr)
32 , m_windowColor(QPalette().window().color())
34 setAcceptHoverEvents(
true);
35 setAcceptedMouseButtons(Qt::AllButtons);
36 connect(
this, &PreviewItem::widthChanged,
this, &PreviewItem::syncSize);
37 connect(
this, &PreviewItem::heightChanged,
this, &PreviewItem::syncSize);
44 m_decoration->deleteLater();
46 m_bridge->unregisterPreviewItem(
this);
52 QQuickPaintedItem::componentComplete();
55 m_decoration->setSettings(m_settings->settings());
61void PreviewItem::createDecoration()
63 if (m_bridge.isNull() || m_settings.isNull() || m_decoration) {
66 Decoration *
decoration = m_bridge->createDecoration(
nullptr);
67 m_client = m_bridge->lastCreatedClient();
78 if (!deco || m_decoration == deco) {
83 m_decoration->setProperty(
"visualParent", QVariant::fromValue(
this));
84 connect(m_decoration, &Decoration::bordersChanged,
this, &PreviewItem::syncSize);
85 connect(m_decoration, &Decoration::shadowChanged,
this, &PreviewItem::syncSize);
87 connect(m_decoration, &Decoration::damaged,
this, [
this]() {
100 if (m_windowColor == color) {
103 m_windowColor = color;
115 int paddingRight = 0;
116 int paddingBottom = 0;
117 paintShadow(painter, paddingLeft, paddingRight, paddingTop, paddingBottom);
118 m_decoration->paint(painter, QRect(0, 0, width(), height()));
119 if (m_drawBackground) {
120 painter->fillRect(m_decoration->borderLeft(), m_decoration->borderTop(),
121 width() - m_decoration->borderLeft() - m_decoration->borderRight() - paddingLeft - paddingRight,
122 height() - m_decoration->borderTop() - m_decoration->borderBottom() - paddingTop - paddingBottom,
127void PreviewItem::paintShadow(QPainter *painter,
int &paddingLeft,
int &paddingRight,
int &paddingTop,
int &paddingBottom)
129 const auto &
shadow = m_decoration->shadow();
134 paddingLeft =
shadow->paddingLeft();
135 paddingTop =
shadow->paddingTop();
136 paddingRight =
shadow->paddingRight();
137 paddingBottom =
shadow->paddingBottom();
139 const QImage shadowPixmap =
shadow->shadow();
140 if (shadowPixmap.isNull()) {
144 const QRect outerRect(-paddingLeft, -paddingTop, width(), height());
145 const QRect shadowRect(shadowPixmap.rect());
147 const QSize topLeftSize(
shadow->topLeftGeometry().size());
149 QPoint(outerRect.x(), outerRect.y()),
152 const QSize topRightSize(
shadow->topRightGeometry().size());
153 QRect topRightTarget(
154 QPoint(outerRect.x() + outerRect.width() - topRightSize.width(),
158 const QSize bottomRightSize(
shadow->bottomRightGeometry().size());
159 QRect bottomRightTarget(
160 QPoint(outerRect.x() + outerRect.width() - bottomRightSize.width(),
161 outerRect.y() + outerRect.height() - bottomRightSize.height()),
164 const QSize bottomLeftSize(
shadow->bottomLeftGeometry().size());
165 QRect bottomLeftTarget(
166 QPoint(outerRect.x(),
167 outerRect.y() + outerRect.height() - bottomLeftSize.height()),
178 if (topLeftTarget.x() + topLeftTarget.width() >= topRightTarget.x()) {
179 const float halfOverlap = std::abs(topLeftTarget.x() + topLeftTarget.width() - topRightTarget.x()) / 2.0f;
180 topLeftTarget.setRight(topLeftTarget.right() - std::floor(halfOverlap));
181 topRightTarget.setLeft(topRightTarget.left() + std::ceil(halfOverlap));
185 bool drawRight =
true;
186 if (topRightTarget.y() + topRightTarget.height() >= bottomRightTarget.y()) {
187 const float halfOverlap = std::abs(topRightTarget.y() + topRightTarget.height() - bottomRightTarget.y()) / 2.0f;
188 topRightTarget.setBottom(topRightTarget.bottom() - std::floor(halfOverlap));
189 bottomRightTarget.setTop(bottomRightTarget.top() + std::ceil(halfOverlap));
193 bool drawBottom =
true;
194 if (bottomLeftTarget.x() + bottomLeftTarget.width() >= bottomRightTarget.x()) {
195 const float halfOverlap = std::abs(bottomLeftTarget.x() + bottomLeftTarget.width() - bottomRightTarget.x()) / 2.0f;
196 bottomLeftTarget.setRight(bottomLeftTarget.right() - std::floor(halfOverlap));
197 bottomRightTarget.setLeft(bottomRightTarget.left() + std::ceil(halfOverlap));
201 bool drawLeft =
true;
202 if (topLeftTarget.y() + topLeftTarget.height() >= bottomLeftTarget.y()) {
203 const float halfOverlap = std::abs(topLeftTarget.y() + topLeftTarget.height() - bottomLeftTarget.y()) / 2.0f;
204 topLeftTarget.setBottom(topLeftTarget.bottom() - std::floor(halfOverlap));
205 bottomLeftTarget.setTop(bottomLeftTarget.top() + std::ceil(halfOverlap));
209 painter->translate(paddingLeft, paddingTop);
211 painter->drawImage(topLeftTarget, shadowPixmap,
212 QRect(QPoint(0, 0), topLeftTarget.size()));
214 painter->drawImage(topRightTarget, shadowPixmap,
215 QRect(QPoint(shadowRect.width() - topRightTarget.width(), 0),
216 topRightTarget.size()));
218 painter->drawImage(bottomRightTarget, shadowPixmap,
219 QRect(QPoint(shadowRect.width() - bottomRightTarget.width(),
220 shadowRect.height() - bottomRightTarget.height()),
221 bottomRightTarget.size()));
223 painter->drawImage(bottomLeftTarget, shadowPixmap,
224 QRect(QPoint(0, shadowRect.height() - bottomLeftTarget.height()),
225 bottomLeftTarget.size()));
228 QRect topTarget(topLeftTarget.x() + topLeftTarget.width(),
230 topRightTarget.x() - topLeftTarget.x() - topLeftTarget.width(),
231 topRightTarget.height());
232 QRect topSource(
shadow->topGeometry());
233 topSource.setHeight(topTarget.height());
234 topSource.moveTop(shadowRect.top());
235 painter->drawImage(topTarget, shadowPixmap, topSource);
239 QRect rightTarget(topRightTarget.x(),
240 topRightTarget.y() + topRightTarget.height(),
241 topRightTarget.width(),
242 bottomRightTarget.y() - topRightTarget.y() - topRightTarget.height());
243 QRect rightSource(
shadow->rightGeometry());
244 rightSource.setWidth(rightTarget.width());
245 rightSource.moveRight(shadowRect.right());
246 painter->drawImage(rightTarget, shadowPixmap, rightSource);
250 QRect bottomTarget(bottomLeftTarget.x() + bottomLeftTarget.width(),
251 bottomLeftTarget.y(),
252 bottomRightTarget.x() - bottomLeftTarget.x() - bottomLeftTarget.width(),
253 bottomRightTarget.height());
254 QRect bottomSource(
shadow->bottomGeometry());
255 bottomSource.setHeight(bottomTarget.height());
256 bottomSource.moveBottom(shadowRect.bottom());
257 painter->drawImage(bottomTarget, shadowPixmap, bottomSource);
261 QRect leftTarget(topLeftTarget.x(),
262 topLeftTarget.y() + topLeftTarget.height(),
263 topLeftTarget.width(),
264 bottomLeftTarget.y() - topLeftTarget.y() - topLeftTarget.height());
265 QRect leftSource(
shadow->leftGeometry());
266 leftSource.setWidth(leftTarget.width());
267 leftSource.moveLeft(shadowRect.left());
268 painter->drawImage(leftTarget, shadowPixmap, leftSource);
272static QMouseEvent cloneEventWithPadding(QMouseEvent *event,
int paddingLeft,
int paddingTop)
276 event->localPos() - QPointF(paddingLeft, paddingTop),
282static QHoverEvent cloneEventWithPadding(QHoverEvent *event,
int paddingLeft,
int paddingTop)
286 event->posF() - QPointF(paddingLeft, paddingTop),
287 event->oldPosF() - QPointF(paddingLeft, paddingTop),
292void PreviewItem::proxyPassEvent(E *event)
const
294 const auto &
shadow = m_decoration->shadow();
296 E e = cloneEventWithPadding(event,
shadow->paddingLeft(),
shadow->paddingTop());
297 QCoreApplication::instance()->sendEvent(
decoration(), &e);
299 QCoreApplication::instance()->sendEvent(
decoration(), event);
307 proxyPassEvent(event);
312 proxyPassEvent(event);
317 proxyPassEvent(event);
322 proxyPassEvent(event);
327 proxyPassEvent(event);
332 proxyPassEvent(event);
337 proxyPassEvent(event);
342 return m_drawBackground;
347 if (m_drawBackground == set) {
350 m_drawBackground = set;
356 return m_bridge.data();
365 m_bridge->unregisterPreviewItem(
this);
369 m_bridge->registerPreviewItem(
this);
376 return m_settings.data();
390 return m_client.data();
393void PreviewItem::syncSize()
399 int heightOffset = 0;
400 auto shadow = m_decoration->shadow();
402 widthOffset =
shadow->paddingLeft() +
shadow->paddingRight();
403 heightOffset =
shadow->paddingTop() +
shadow->paddingBottom();
405 m_client->setWidth(width() - m_decoration->borderLeft() - m_decoration->borderRight() - widthOffset);
406 m_client->setHeight(height() - m_decoration->borderTop() - m_decoration->borderBottom() - heightOffset);
414 return m_decoration->shadow().get();
420#include "moc_previewitem.cpp"
KDecoration2::DecorationShadow * shadow
void mousePressEvent(QMouseEvent *event) override
void hoverMoveEvent(QHoverEvent *event) override
void paint(QPainter *painter) override
void hoverEnterEvent(QHoverEvent *event) override
void setWindowColor(const QColor &color)
void setSettings(Settings *settings)
void decorationChanged(KDecoration2::Decoration *deco)
void componentComplete() override
void mouseDoubleClickEvent(QMouseEvent *event) override
KDecoration2::Preview::PreviewClient * client
KDecoration2::Decoration * decoration
void hoverLeaveEvent(QHoverEvent *event) override
PreviewItem(QQuickItem *parent=nullptr)
void drawingBackgroundChanged(bool)
void windowColorChanged(const QColor &color)
KDecoration2::Preview::PreviewBridge * bridge
void setDrawingBackground(bool set)
KDecoration2::Preview::Settings * settings
void mouseMoveEvent(QMouseEvent *event) override
void mouseReleaseEvent(QMouseEvent *event) override
void setDecoration(KDecoration2::Decoration *deco)
void setBridge(PreviewBridge *bridge)
bool isDrawingBackground() const