File indexing completed on 2024-05-26 05:38:26
0001 /* 0002 SPDX-FileCopyrightText: 2014 David Edmundson <kde@davidedmundson.co.uk> 0003 SPDX-FileCopyrightText: 2014 Eike Hein <hein@kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "submenu.h" 0009 0010 #include <cmath> 0011 0012 #include <QScreen> 0013 0014 #include <KWindowSystem> 0015 0016 SubMenu::SubMenu(QQuickItem *parent) 0017 : PlasmaQuick::Dialog(parent) 0018 , m_offset(0) 0019 , m_facingLeft(false) 0020 { 0021 setType(AppletPopup); 0022 } 0023 0024 SubMenu::~SubMenu() 0025 { 0026 } 0027 0028 int SubMenu::offset() const 0029 { 0030 return m_offset; 0031 } 0032 0033 void SubMenu::setOffset(int offset) 0034 { 0035 if (m_offset != offset) { 0036 m_offset = offset; 0037 0038 Q_EMIT offsetChanged(); 0039 } 0040 } 0041 0042 QPoint SubMenu::popupPosition(QQuickItem *item, const QSize &size) 0043 { 0044 if (!item || !item->window()) { 0045 return QPoint(0, 0); 0046 } 0047 0048 QPointF pos = item->mapToScene(QPointF(0, 0)); 0049 pos = item->window()->mapToGlobal(pos.toPoint()); 0050 0051 pos.setX(pos.x() + m_offset + item->width()); 0052 0053 QRect avail = availableScreenRectForItem(item); 0054 0055 if (pos.x() + size.width() > avail.right()) { 0056 pos.setX(pos.x() - m_offset - item->width() - size.width()); 0057 0058 m_facingLeft = true; 0059 Q_EMIT facingLeftChanged(); 0060 } 0061 0062 pos.setY(pos.y() - margins()->property("top").toInt()); 0063 0064 if (pos.y() + size.height() > avail.bottom()) { 0065 int overshoot = std::ceil(((avail.bottom() - (pos.y() + size.height())) * -1) / item->height()) * item->height(); 0066 0067 pos.setY(pos.y() - overshoot); 0068 } 0069 0070 return pos.toPoint(); 0071 } 0072 0073 QRect SubMenu::availableScreenRectForItem(QQuickItem *item) const 0074 { 0075 QScreen *screen = QGuiApplication::primaryScreen(); 0076 0077 const QPoint globalPosition = item->window()->mapToGlobal(item->position().toPoint()); 0078 0079 const QList<QScreen *> screens = QGuiApplication::screens(); 0080 for (QScreen *s : screens) { 0081 if (s->geometry().contains(globalPosition)) { 0082 screen = s; 0083 } 0084 } 0085 0086 return screen->availableGeometry(); 0087 }