File indexing completed on 2024-04-21 05:54:03

0001 /*
0002     SPDX-FileCopyrightText: 2009 Tom Albers <toma@kde.org>
0003     SPDX-FileCopyrightText: 2010 Juan Luis Baptiste <juan.baptiste@gmail.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "breakbase.h"
0009 #include "breakcontrol.h"
0010 
0011 #include <KWindowSystem>
0012 
0013 #include <QApplication>
0014 #include <QDebug>
0015 #include <QKeyEvent>
0016 #include <QObject>
0017 #include <QPainter>
0018 #include <QScreen>
0019 
0020 BreakBase::BreakBase(QObject *parent)
0021     : QObject(parent)
0022     , m_grayEffectOnAllScreens(nullptr)
0023     , m_readOnly(false)
0024     , m_disableShortcut(false)
0025     , m_grayEffectOnAllScreensActivated(false)
0026 {
0027     m_breakControl = new BreakControl(nullptr, Qt::Popup);
0028     m_breakControl->hide();
0029     m_breakControl->installEventFilter(this);
0030     connect(m_breakControl, &BreakControl::skip, this, &BreakBase::skip);
0031     connect(m_breakControl, &BreakControl::lock, this, &BreakBase::lock);
0032     connect(m_breakControl, &BreakControl::postpone, this, &BreakBase::postpone);
0033 }
0034 
0035 BreakBase::~BreakBase()
0036 {
0037     delete m_grayEffectOnAllScreens;
0038     delete m_breakControl;
0039 }
0040 
0041 void BreakBase::activate()
0042 {
0043     if (m_grayEffectOnAllScreensActivated)
0044         m_grayEffectOnAllScreens->activate();
0045 
0046     m_breakControl->show();
0047     m_breakControl->setFocus();
0048 
0049     KWindowSystem::forceActiveWindow(m_breakControl->winId());
0050     KWindowSystem::setOnAllDesktops(m_breakControl->winId(), true);
0051     KWindowSystem::setState(m_breakControl->winId(), NET::KeepAbove);
0052     KWindowSystem::setState(m_breakControl->winId(), NET::FullScreen);
0053 
0054     m_breakControl->grabKeyboard();
0055     m_breakControl->grabMouse();
0056 }
0057 
0058 void BreakBase::deactivate()
0059 {
0060     if (m_grayEffectOnAllScreensActivated)
0061         m_grayEffectOnAllScreens->deactivate();
0062 
0063     m_breakControl->releaseMouse();
0064     m_breakControl->releaseKeyboard();
0065     m_breakControl->hide();
0066 }
0067 
0068 bool BreakBase::eventFilter(QObject *obj, QEvent *event)
0069 {
0070     if (event->type() == QEvent::KeyPress) {
0071         QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
0072         qDebug() << "Ate key press" << keyEvent->key();
0073         if (!m_disableShortcut && keyEvent->key() == Qt::Key_Escape) {
0074             qDebug() << "Escape";
0075             emit skip();
0076         }
0077         return true;
0078     } else if (m_readOnly && (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick)) {
0079         qDebug() << "Ate mouse click event";
0080         return true;
0081     } else {
0082         return QObject::eventFilter(obj, event);
0083     }
0084 }
0085 
0086 void BreakBase::setReadOnly(bool ro)
0087 {
0088     m_readOnly = ro;
0089 }
0090 
0091 bool BreakBase::readOnly() const
0092 {
0093     return m_readOnly;
0094 }
0095 
0096 void BreakBase::setLabel(const QString &text)
0097 {
0098     m_breakControl->setText(text);
0099 }
0100 
0101 void BreakBase::showMinimize(bool show)
0102 {
0103     m_breakControl->showMinimize(show);
0104 }
0105 
0106 void BreakBase::showLock(bool show)
0107 {
0108     m_breakControl->showLock(show);
0109 }
0110 
0111 void BreakBase::showPostpone(bool show)
0112 {
0113     m_breakControl->showPostpone(show);
0114 }
0115 
0116 void BreakBase::disableShortcut(bool disable)
0117 {
0118     m_disableShortcut = disable;
0119 }
0120 
0121 void BreakBase::setGrayEffectOnAllScreens(bool on)
0122 {
0123     m_grayEffectOnAllScreensActivated = on;
0124     delete m_grayEffectOnAllScreens;
0125     if (on) {
0126         m_grayEffectOnAllScreens = new GrayEffectOnAllScreens();
0127         m_grayEffectOnAllScreens->setLevel(70);
0128     }
0129 }
0130 
0131 void BreakBase::setGrayEffectLevel(int level)
0132 {
0133     m_grayEffectOnAllScreens->setLevel(level);
0134 }
0135 
0136 void BreakBase::excludeGrayEffectOnScreen(QScreen *screen)
0137 {
0138     m_grayEffectOnAllScreens->disable(screen);
0139 }
0140 
0141 // ------------------------ GrayEffectOnAllScreens -------------//
0142 
0143 GrayEffectOnAllScreens::GrayEffectOnAllScreens()
0144 {
0145     for (QScreen *screen : QGuiApplication::screens()) {
0146         GrayWidget *grayWidget = new GrayWidget(nullptr);
0147         m_widgets.insert(screen, grayWidget);
0148 
0149         const QRect rect = screen->geometry();
0150         grayWidget->move(rect.topLeft());
0151         grayWidget->setGeometry(rect);
0152 
0153         KWindowSystem::forceActiveWindow(grayWidget->winId());
0154         KWindowSystem::setState(grayWidget->winId(), NET::KeepAbove);
0155         KWindowSystem::setOnAllDesktops(grayWidget->winId(), true);
0156         KWindowSystem::setState(grayWidget->winId(), NET::FullScreen);
0157 
0158         qDebug() << "Created widget for screen" << screen << "Position:" << rect.topLeft();
0159     }
0160 }
0161 
0162 GrayEffectOnAllScreens::~GrayEffectOnAllScreens()
0163 {
0164     qDeleteAll(m_widgets);
0165 }
0166 
0167 void GrayEffectOnAllScreens::disable(QScreen *screen)
0168 {
0169     qDebug() << "Removing widget from screen" << screen;
0170     if (!m_widgets.contains(screen))
0171         return;
0172 
0173     delete m_widgets.take(screen);
0174 }
0175 
0176 void GrayEffectOnAllScreens::activate()
0177 {
0178     foreach (GrayWidget *widget, m_widgets) {
0179         widget->show();
0180         widget->update();
0181     }
0182 }
0183 
0184 void GrayEffectOnAllScreens::deactivate()
0185 {
0186     foreach (GrayWidget *widget, m_widgets) {
0187         widget->hide();
0188     }
0189 }
0190 
0191 void GrayEffectOnAllScreens::setLevel(int val)
0192 {
0193     foreach (GrayWidget *widget, m_widgets) {
0194         widget->setLevel(val);
0195     }
0196 }
0197 
0198 //-------------------- GrayWidget ----------------------------//
0199 
0200 GrayWidget::GrayWidget(QWidget *parent)
0201     : QWidget(parent, Qt::Popup)
0202 {
0203     setAutoFillBackground(false);
0204 }
0205 
0206 bool GrayWidget::event(QEvent *event)
0207 {
0208     if (event->type() == QEvent::Paint) {
0209         qDebug() << "GrayWidget::event";
0210         QPainter p(this);
0211         p.setCompositionMode(QPainter::CompositionMode_Source);
0212         p.fillRect(rect(), QColor(0, 0, 0, 180));
0213     }
0214     return QWidget::event(event);
0215 }
0216 
0217 void GrayWidget::setLevel(int val)
0218 {
0219     double level = 0;
0220     if (val > 0)
0221         level = (double)val / 100;
0222 
0223     qDebug() << "New Value" << level;
0224     setWindowOpacity(level);
0225     update();
0226 }