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"