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();
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;
49PopupPlasmaWindowPrivate::PopupPlasmaWindowPrivate(PopupPlasmaWindow *_q)
61void PopupPlasmaWindowPrivate::updateEffectivePopupDirection(
const QRect &anchorRect,
const QRect &relativePopupPosition)
65 if (relativePopupPosition.
center().
y() >= anchorRect.
center().
y()) {
72 if (relativePopupPosition.
center().
x() >= anchorRect.
center().
x()) {
79 if (effectivePopupDirection != m_effectivePopupDirection) {
80 Q_EMIT q->effectivePopupDirectionChanged();
81 m_effectivePopupDirection = effectivePopupDirection;
85void PopupPlasmaWindowPrivate::updateSlideEffect()
87 KWindowEffects::SlideFromLocation slideLocation = KWindowEffects::NoEdge;
92 switch (m_effectivePopupDirection) {
94 slideLocation = KWindowEffects::BottomEdge;
97 slideLocation = KWindowEffects::TopEdge;
100 slideLocation = KWindowEffects::RightEdge;
103 slideLocation = KWindowEffects::LeftEdge;
109void PopupPlasmaWindowPrivate::updatePosition()
111 m_needsReposition =
false;
113 if (!m_visualParent || !m_visualParent->window()) {
114 qCWarning(LOG_PLASMAQUICK) <<
"Exposed with no visual parent. Window positioning broken.";
117 q->setTransientParent(m_visualParent->window());
118 TransientPlacementHint placementHint;
119 QRectF parentAnchorRect =
QRectF(m_visualParent->mapToScene(
QPointF(0, 0)), m_visualParent->size());
122 QRect windowVisibleRect = m_visualParent->window()->mask().boundingRect();
126 parentAnchorRect.
setTop(windowVisibleRect.
top());
131 parentAnchorRect.
setLeft(windowVisibleRect.
left());
137 placementHint.setParentAnchorArea(parentAnchorRect.
toRect());
138 placementHint.setParentAnchor(m_popupDirection);
139 placementHint.setPopupAnchor(PlasmaQuickPrivate::oppositeEdge(m_popupDirection));
140 placementHint.setConstrainByAnchorWindow(
true);
142 placementHint.setMargin(m_margin);
144 const QRect popupPosition = TransientPlacementHelper::popupRect(q, placementHint);
146 QRect relativePopupPosition = popupPosition;
147 if (m_visualParent->window()) {
148 relativePopupPosition = relativePopupPosition.
translated(-m_visualParent->window()->position());
150 updateEffectivePopupDirection(parentAnchorRect.
toRect(), relativePopupPosition);
154 updatePositionX11(popupPosition.
topLeft());
156 updatePositionWayland(popupPosition.
topLeft());
159 updateBorders(popupPosition);
162void PopupPlasmaWindowPrivate::updatePositionX11(
const QPoint &position)
164 q->setPosition(position);
167void PopupPlasmaWindowPrivate::updatePositionWayland(
const QPoint &position)
171 q->setPosition(position);
176void PopupPlasmaWindowPrivate::updateBorders(
const QRect &globalPosition)
189 q->setBorders(enabledBorders);
193 if (m_removeBorderStrategy & PopupPlasmaWindow::AtScreenEdges) {
194 if (globalPosition.
top() <= screenGeometry.
top()) {
197 if (globalPosition.
bottom() >= screenGeometry.
bottom()) {
200 if (globalPosition.
left() <= screenGeometry.
left()) {
203 if (globalPosition.
right() >= screenGeometry.
right()) {
207 if (m_removeBorderStrategy & PopupPlasmaWindow::AtPanelEdges) {
208 switch (m_popupDirection) {
224 q->setBorders(enabledBorders);
227void PopupPlasmaWindowPrivate::updateVisualParentWindow()
229 if (m_visualParentWindow) {
234 m_visualParentWindow = m_visualParent ? m_visualParent->window() :
nullptr;
236 if (m_visualParentWindow) {
242PopupPlasmaWindow::PopupPlasmaWindow(
const QString &svgPrefix)
243 : PlasmaWindow(svgPrefix)
244 , d(new PopupPlasmaWindowPrivate(this))
248PopupPlasmaWindow::~PopupPlasmaWindow()
252void PopupPlasmaWindow::setVisualParent(
QQuickItem *item)
254 if (item == d->m_visualParent) {
258 if (d->m_visualParent) {
259 disconnect(d->m_visualParent, SIGNAL(windowChanged(
QQuickWindow *)),
this, SLOT(updateVisualParentWindow()));
262 d->m_visualParent = item;
263 d->updateVisualParentWindow();
265 if (d->m_visualParent) {
266 connect(d->m_visualParent, SIGNAL(windowChanged(
QQuickWindow *)),
this, SLOT(updateVisualParentWindow()));
269 Q_EMIT visualParentChanged();
270 queuePositionUpdate();
273QQuickItem *PopupPlasmaWindow::visualParent()
const
275 return d->m_visualParent;
278Qt::Edge PopupPlasmaWindow::popupDirection()
const
280 return d->m_popupDirection;
283void PopupPlasmaWindow::setPopupDirection(
Qt::Edge popupDirection)
285 if (popupDirection == d->m_popupDirection) {
288 d->m_popupDirection = popupDirection;
291 qCWarning(LOG_PLASMAQUICK) <<
"location should be set before showing popup window";
293 queuePositionUpdate();
295 Q_EMIT popupDirectionChanged();
298Qt::Edge PopupPlasmaWindow::effectivePopupDirection()
const
300 return d->m_effectivePopupDirection;
303bool PopupPlasmaWindow::floating()
const
305 return d->m_floating;
308void PopupPlasmaWindow::setFloating(
bool floating)
310 if (floating == d->m_floating) {
313 d->m_floating = floating;
314 queuePositionUpdate();
315 Q_EMIT floatingChanged();
318bool PopupPlasmaWindow::animated()
const
320 return d->m_animated;
323void PopupPlasmaWindow::setAnimated(
bool animated)
325 d->m_animated = animated;
326 queuePositionUpdate();
327 Q_EMIT animatedChanged();
330PopupPlasmaWindow::RemoveBorders PopupPlasmaWindow::removeBorderStrategy()
const
332 return d->m_removeBorderStrategy;
335void PopupPlasmaWindow::setRemoveBorderStrategy(PopupPlasmaWindow::RemoveBorders strategy)
337 if (d->m_removeBorderStrategy == strategy) {
341 d->m_removeBorderStrategy = strategy;
342 queuePositionUpdate();
343 Q_EMIT removeBorderStrategyChanged();
346int PopupPlasmaWindow::margin()
const
351void PopupPlasmaWindow::setMargin(
int margin)
353 if (d->m_margin == margin) {
357 d->m_margin = margin;
358 queuePositionUpdate();
359 Q_EMIT marginChanged();
362bool PopupPlasmaWindow::event(
QEvent *event)
364 switch (
event->type()) {
366 if (d->m_needsReposition) {
382void PopupPlasmaWindow::queuePositionUpdate()
384 d->m_needsReposition =
true;
388#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)
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)
virtual bool event(QEvent *ev) override