File indexing completed on 2025-02-02 04:26:12

0001 /* SPDX-FileCopyrightText: 2022 Noah Davis <noahadvs@gmail.com>
0002  * SPDX-License-Identifier: LGPL-2.0-or-later
0003  */
0004 
0005 #include "SpectacleMenu.h"
0006 #include "WidgetWindowUtils.h"
0007 #include <QQuickItem>
0008 #include <QQuickWindow>
0009 #include <QScreen>
0010 #include <QTimer>
0011 
0012 SpectacleMenu::SpectacleMenu(const QString &title, QWidget *parent)
0013     : QMenu(title, parent)
0014 {
0015     setAttribute(Qt::WA_TranslucentBackground);
0016 }
0017 
0018 SpectacleMenu::SpectacleMenu(QWidget *parent)
0019     : QMenu(parent)
0020 {
0021     setAttribute(Qt::WA_TranslucentBackground);
0022 }
0023 
0024 void SpectacleMenu::setVisible(bool visible)
0025 {
0026     bool oldVisible = isVisible();
0027     if (oldVisible == visible) {
0028         return;
0029     }
0030     // Workaround for a bug where Qt Quick buttons always open the menu even when the menu is already open
0031     if (visible) {
0032         QMenu::setVisible(true);
0033     } else {
0034         QTimer::singleShot(200, this, [this] {
0035             QMenu::setVisible(false);
0036         });
0037     }
0038 }
0039 
0040 void SpectacleMenu::popup(QQuickItem *item)
0041 {
0042     if (!item || !item->window()) {
0043         return;
0044     }
0045     auto itemWindow = item->window();
0046     auto point = item->mapToGlobal({0, item->height()});
0047     auto screenRect = itemWindow->screen()->geometry();
0048     auto sizeHint = this->sizeHint();
0049     if (point.y() + sizeHint.height() > screenRect.bottom()) {
0050         point.setY(point.y() - item->height() - sizeHint.height());
0051     }
0052     if (point.x() + sizeHint.width() > screenRect.right()) {
0053         point.setX(point.x() - sizeHint.width() + item->width());
0054     }
0055     setWidgetTransientParent(this, itemWindow);
0056     // Workaround same as plasma to have click anywhereto close the menu
0057     QTimer::singleShot(0, this, [this, itemWindow, point]() {
0058         if (itemWindow->mouseGrabberItem()) {
0059             itemWindow->mouseGrabberItem()->ungrabMouse();
0060         }
0061         QMenu::popup(point.toPoint());
0062     });
0063 }
0064 
0065 void SpectacleMenu::showEvent(QShowEvent *event)
0066 {
0067     QMenu::showEvent(event);
0068     Q_EMIT visibleChanged();
0069 }
0070 
0071 void SpectacleMenu::hideEvent(QHideEvent *event)
0072 {
0073     QMenu::hideEvent(event);
0074     Q_EMIT visibleChanged();
0075 }
0076 
0077 #include "moc_SpectacleMenu.cpp"