6#include "popupplasmawindow.h"
8#include <kwindoweffects.h>
9#include <kwindowsystem.h>
12#include <QGuiApplication>
14#include <qnamespace.h>
15#include <qtmetamacros.h>
17#include "plasmashellwaylandintegration.h"
18#include "transientplacementhint_p.h"
24class PopupPlasmaWindowPrivate
27 PopupPlasmaWindowPrivate(PopupPlasmaWindow *_q);
29 void updateEffectivePopupDirection(
const QRect &anchorRect,
const QRect &relativePopupPosition);
30 void updateSlideEffect(
const QRect &globalPosition);
31 void updatePosition();
32 void updatePositionX11(
const QPoint &position);
33 void updatePositionWayland(
const QPoint &position);
34 void updateBorders(
const QRect &globalPosition);
35 void updateVisualParentWindow();
40 PopupPlasmaWindow::RemoveBorders m_removeBorderStrategy = PopupPlasmaWindow::Never;
41 bool m_needsReposition =
false;
42 bool m_floating =
false;
43 bool m_animated =
false;
50PopupPlasmaWindowPrivate::PopupPlasmaWindowPrivate(PopupPlasmaWindow *_q)
62void PopupPlasmaWindowPrivate::updateEffectivePopupDirection(
const QRect &anchorRect,
const QRect &relativePopupPosition)
66 if (relativePopupPosition.
center().
y() >= anchorRect.
center().
y()) {
73 if (relativePopupPosition.
center().
x() >= anchorRect.
center().
x()) {
80 if (effectivePopupDirection != m_effectivePopupDirection) {
81 Q_EMIT q->effectivePopupDirectionChanged();
82 m_effectivePopupDirection = effectivePopupDirection;
86void PopupPlasmaWindowPrivate::updateSlideEffect(
const QRect &globalPosition)
88 KWindowEffects::SlideFromLocation slideLocation = KWindowEffects::NoEdge;
92 if (screen && m_margin > 0) {
94 switch (m_effectivePopupDirection) {
96 slideOffset = screenGeometry.
bottom() - globalPosition.
bottom() - m_margin;
99 slideOffset = globalPosition.
top() - screenGeometry.
top() - m_margin;
102 slideOffset = screenGeometry.
right() - globalPosition.
right() - m_margin;
105 slideOffset = globalPosition.
left() - screenGeometry.
left() - m_margin;
114 switch (m_effectivePopupDirection) {
116 slideLocation = KWindowEffects::BottomEdge;
119 slideLocation = KWindowEffects::TopEdge;
122 slideLocation = KWindowEffects::RightEdge;
125 slideLocation = KWindowEffects::LeftEdge;
131void PopupPlasmaWindowPrivate::updatePosition()
133 m_needsReposition =
false;
135 if (!m_visualParent || !m_visualParent->window()) {
136 qCWarning(LOG_PLASMAQUICK) <<
"Exposed with no visual parent. Window positioning broken.";
139 q->setTransientParent(m_visualParent->window());
140 TransientPlacementHint placementHint;
141 QRectF parentAnchorRect =
QRectF(m_visualParent->mapToScene(
QPointF(0, 0)), m_visualParent->size());
144 QRect windowVisibleRect = m_visualParent->window()->mask().boundingRect();
148 parentAnchorRect.
setTop(windowVisibleRect.
top());
153 parentAnchorRect.
setLeft(windowVisibleRect.
left());
159 placementHint.setParentAnchorArea(parentAnchorRect.
toRect());
160 placementHint.setParentAnchor(m_popupDirection);
161 placementHint.setPopupAnchor(PlasmaQuickPrivate::oppositeEdge(m_popupDirection));
162 placementHint.setConstrainByAnchorWindow(
true);
164 placementHint.setMargin(m_margin);
166 const QRect popupPosition = TransientPlacementHelper::popupRect(q, placementHint);
168 QRect relativePopupPosition = popupPosition;
169 if (m_visualParent->window()) {
170 relativePopupPosition = relativePopupPosition.
translated(-m_visualParent->window()->position());
172 updateEffectivePopupDirection(parentAnchorRect.
toRect(), relativePopupPosition);
173 updateSlideEffect(popupPosition);
176 updatePositionX11(popupPosition.
topLeft());
178 updatePositionWayland(popupPosition.
topLeft());
181 updateBorders(popupPosition);
184void PopupPlasmaWindowPrivate::updatePositionX11(
const QPoint &position)
186 q->setPosition(position);
189void PopupPlasmaWindowPrivate::updatePositionWayland(
const QPoint &position)
193 q->setPosition(position);
198void PopupPlasmaWindowPrivate::updateBorders(
const QRect &globalPosition)
210 if (m_removeBorderStrategy & PopupPlasmaWindow::AtScreenEdges) {
211 if (globalPosition.
top() - m_margin <= screenGeometry.
top()) {
214 if (globalPosition.
bottom() + m_margin >= screenGeometry.
bottom()) {
217 if (globalPosition.
left() - m_margin <= screenGeometry.
left()) {
220 if (globalPosition.
right() + m_margin >= screenGeometry.
right()) {
224 if (m_removeBorderStrategy & PopupPlasmaWindow::AtPanelEdges) {
225 switch (m_popupDirection) {
242 Qt::Edges newNearbyBorders = ~enabledBorders;
251 newNearbyBorders.setFlag(PlasmaQuickPrivate::oppositeEdge(m_effectivePopupDirection),
true);
253 if (newNearbyBorders != m_nearbyBorders) {
254 m_nearbyBorders = newNearbyBorders;
255 Q_EMIT q->nearbyBordersChanged();
263 q->setBorders(enabledBorders);
266void PopupPlasmaWindowPrivate::updateVisualParentWindow()
268 if (m_visualParentWindow) {
273 m_visualParentWindow = m_visualParent ? m_visualParent->window() :
nullptr;
275 if (m_visualParentWindow) {
281PopupPlasmaWindow::PopupPlasmaWindow(
const QString &svgPrefix)
282 : PlasmaWindow(svgPrefix)
283 , d(new PopupPlasmaWindowPrivate(this))
287PopupPlasmaWindow::~PopupPlasmaWindow()
291void PopupPlasmaWindow::setVisualParent(
QQuickItem *item)
293 if (item == d->m_visualParent) {
297 if (d->m_visualParent) {
298 disconnect(d->m_visualParent, SIGNAL(windowChanged(
QQuickWindow *)),
this, SLOT(updateVisualParentWindow()));
301 d->m_visualParent = item;
302 d->updateVisualParentWindow();
304 if (d->m_visualParent) {
305 connect(d->m_visualParent, SIGNAL(windowChanged(
QQuickWindow *)),
this, SLOT(updateVisualParentWindow()));
308 Q_EMIT visualParentChanged();
309 queuePositionUpdate();
312QQuickItem *PopupPlasmaWindow::visualParent()
const
314 return d->m_visualParent;
317Qt::Edge PopupPlasmaWindow::popupDirection()
const
319 return d->m_popupDirection;
322void PopupPlasmaWindow::setPopupDirection(
Qt::Edge popupDirection)
324 if (popupDirection == d->m_popupDirection) {
327 d->m_popupDirection = popupDirection;
330 qCWarning(LOG_PLASMAQUICK) <<
"location should be set before showing popup window";
332 queuePositionUpdate();
334 Q_EMIT popupDirectionChanged();
337Qt::Edge PopupPlasmaWindow::effectivePopupDirection()
const
339 return d->m_effectivePopupDirection;
342bool PopupPlasmaWindow::floating()
const
344 return d->m_floating;
347void PopupPlasmaWindow::setFloating(
bool floating)
349 if (floating == d->m_floating) {
352 d->m_floating = floating;
353 queuePositionUpdate();
354 Q_EMIT floatingChanged();
357bool PopupPlasmaWindow::animated()
const
359 return d->m_animated;
362void PopupPlasmaWindow::setAnimated(
bool animated)
364 d->m_animated = animated;
365 queuePositionUpdate();
366 Q_EMIT animatedChanged();
369PopupPlasmaWindow::RemoveBorders PopupPlasmaWindow::removeBorderStrategy()
const
371 return d->m_removeBorderStrategy;
374void PopupPlasmaWindow::setRemoveBorderStrategy(PopupPlasmaWindow::RemoveBorders strategy)
376 if (d->m_removeBorderStrategy == strategy) {
380 d->m_removeBorderStrategy = strategy;
381 queuePositionUpdate();
382 Q_EMIT removeBorderStrategyChanged();
385int PopupPlasmaWindow::margin()
const
390Qt::Edges PopupPlasmaWindow::nearbyBorders()
const
392 return d->m_nearbyBorders;
395void PopupPlasmaWindow::setMargin(
int margin)
397 if (d->m_margin == margin) {
401 d->m_margin = margin;
402 queuePositionUpdate();
403 Q_EMIT marginChanged();
406bool PopupPlasmaWindow::event(
QEvent *event)
408 switch (
event->type()) {
410 if (d->m_needsReposition) {
426void PopupPlasmaWindow::queuePositionUpdate()
428 d->m_needsReposition =
true;
432#include "moc_popupplasmawindow.cpp"
static bool isPlatformX11()
static bool isPlatformWayland()
static PlasmaShellWaylandIntegration * get(QWindow *window)
Returns the relevant PlasmaWaylandShellIntegration instance for this window creating one if needed.
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
void slideWindow(QWindow *window, SlideFromLocation location, int offset=-1)
The EdgeEventForwarder class This class forwards edge events to be replayed within the given margin T...
QScreen * screenAt(const QPoint &point)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
virtual bool event(QEvent *event) override
QPoint center() const const
QPoint topLeft() const const
QRect translated(const QPoint &offset) const const
QRect toRect() const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)