#include "lts_screen_container.h" #include "lts_dummy_widget.h" #include #include #include #include #include #include namespace LtsMultiMonitor { QString LtsScreenContainer::geoStr() const { return QStringLiteral("%1:%2:") .arg(QString::number(m_screenGeo.x()).rightJustified(4, QLatin1Char(' '))) .arg(QString::number(m_screenGeo.y()).rightJustified(4, QLatin1Char(' '))) ; } LtsScreenContainer::LtsScreenContainer(QRect screenGeo) : m_layout(new QHBoxLayout) , m_screenGeo(screenGeo) { m_layout->setMargin(0); m_layout->setSpacing(0); m_layout->setStretch(0, 999); setContentsMargins(0, 0, 0, 0); vanish(); setLayout(m_layout); QTimer *t = new QTimer(this); t->setInterval(3000); #ifdef LTS_DEBUG t->start(); #endif connect(t, &QTimer::timeout, this, [this, screenGeo]() { QString old(QStringLiteral("<#!UNKNOWN!#>")); if (m_oldActiveWidget == nullptr) old = QStringLiteral("null"); else if (m_oldActiveWidget == &m_mainWidget) old = QStringLiteral("MAIN"); else if (m_oldActiveWidget == &m_secondaryWidget) old = QStringLiteral("SECONDARY"); }); } bool LtsScreenContainer::isInactiveWidgetOccupied() const { if (m_activeWidget == &m_mainWidget && m_secondaryWidget != nullptr) return true; if (m_activeWidget == &m_secondaryWidget && m_mainWidget != nullptr) return true; return false; } QIcon LtsScreenContainer::mainWindowIcon() const { if (m_mainWidget != nullptr) return m_mainWidget->windowIcon(); return {}; } QIcon LtsScreenContainer::secondaryWindowIcon() const { if (m_secondaryWidget != nullptr) return m_secondaryWidget->windowIcon(); return {}; } bool LtsScreenContainer::mainAndSecondaryOccupied() const { return (m_mainWidget != nullptr && m_secondaryWidget != nullptr); } LtsScreenBase::WidgetType LtsScreenContainer::activeWidgetType() const { if (m_activeWidget == &m_mainWidget) return LtsScreenBase::WidgetType::MainWidget; if (m_activeWidget == &m_secondaryWidget) return LtsScreenBase::WidgetType::SecondaryWidget; assert(false); return LtsScreenBase::WidgetType::None; } void LtsScreenContainer::toggle() { switchToTemp((*m_activeWidget == m_mainWidget) ? LtsScreenBase::WidgetType::SecondaryWidget : LtsScreenBase::WidgetType::MainWidget); QWidget *w = activeWidget(); assert(w != nullptr); if (w == nullptr) { revertSwitch(); return; } if (!tryPutDummyUnmanaged(w)) w->show(); finalizeSwitch(); } bool LtsScreenContainer::isIrreplaceable() const { if (m_activeWidget == nullptr) return false; auto *blw = qobject_cast(activeWidget()); if (blw == nullptr) return false; return blw->isIrreplaceable(); } QWidget *LtsScreenContainer::activeWidget() const { assert(m_activeWidget != nullptr); return *m_activeWidget; } QWidget **LtsScreenContainer::activeWidgetPtr() { assert(m_activeWidget != nullptr); return m_activeWidget; } void LtsScreenContainer::vanish() { return; m_layout->setParent(nullptr); } void LtsScreenContainer::reappear() { return; setAttribute(Qt::WA_TranslucentBackground, false); if (m_layout->parent() == nullptr) setLayout(m_layout); } QWidget *LtsScreenContainer::stealWidget() noexcept(false) { QWidget **widgetPtr = activeWidgetPtr(); QWidget *widget = *widgetPtr; if (widget == nullptr) { throw "stealWidget: no widget to steal"; } widget->setParent(nullptr); vanish(); disconnect(widget, &QWidget::destroyed, this, &LtsScreenContainer::slotChildDestroyed); QWidget *oldWidget = widget; *widgetPtr = nullptr; return oldWidget; } bool LtsScreenContainer::hasWidget(QWidget *widget) const { if (m_mainWidget != nullptr && m_mainWidget == widget) return true; if (m_secondaryWidget != nullptr && m_secondaryWidget == widget) return true; return false; } bool LtsScreenContainer::isEmpty() const { QWidget **currentWidgetPtr = m_activeWidget; if (currentWidgetPtr == nullptr) return true; return (*currentWidgetPtr == nullptr); } bool LtsScreenContainer::hasMainWidget() { return m_mainWidget != nullptr; } bool LtsScreenContainer::hasSecondaryWidget() { return m_secondaryWidget != nullptr; } bool LtsScreenContainer::tryPutDummyUnmanaged(QWidget *widget) { auto *dummy = qobject_cast(widget); if (dummy == nullptr) return false; QRect r(mapToGlobal(rect().topLeft()), rect().size()); emit dummy->signalWidgetPlaced(r); emit signalSetCornerIcons(); return true; } void LtsScreenContainer::switchToTemp(LtsScreenBase::WidgetType widgetType) { Q_ASSERT(widgetType != LtsScreenBase::WidgetType::None); if ((m_activeWidget == &m_mainWidget && widgetType == LtsScreenBase::WidgetType::MainWidget) || (m_activeWidget == &m_secondaryWidget && widgetType == LtsScreenBase::WidgetType::SecondaryWidget)) { m_nullSwitchActive = true; return; } if (widgetType == LtsScreenBase::WidgetType::MainWidget) m_oldActiveWidget = &m_secondaryWidget; else if (widgetType == LtsScreenBase::WidgetType::SecondaryWidget) m_oldActiveWidget = &m_mainWidget; else Q_ASSERT(false); m_activeWidget = (widgetType == LtsScreenBase::WidgetType::SecondaryWidget ? &m_secondaryWidget : &m_mainWidget); } void LtsScreenContainer::finalizeSwitch() { QWidget **oldActiveWidget = m_oldActiveWidget; m_oldActiveWidget = nullptr; if (m_nullSwitchActive) { m_nullSwitchActive = false; return; } if (oldActiveWidget == nullptr) { return; } if (*oldActiveWidget == nullptr) { return; } QWidget *widget = *oldActiveWidget; auto *dummy = qobject_cast(widget); if (dummy != nullptr) { dummy->hideVideo(); } else { widget->hide(); } QWidget *widget2 = *m_activeWidget; auto *dummy2 = qobject_cast(widget2); if (dummy2 != nullptr) { dummy2->showVideo(); } emit signalSetCornerIcons(); } void LtsScreenContainer::revertSwitch() { QWidget **oldActiveWidgetBackup = m_oldActiveWidget; m_oldActiveWidget = nullptr; if (m_nullSwitchActive) { m_nullSwitchActive = false; return; } if (oldActiveWidgetBackup == nullptr) return; m_activeWidget = oldActiveWidgetBackup; } void LtsScreenContainer::setWidget(QWidget *widget) { QWidget **widgetPtr = activeWidgetPtr(); qWarning() << geoStr() << "setWidget: m_activeWidget" << m_activeWidget; QWidget *currentWidget = *widgetPtr; Q_ASSERT(currentWidget == nullptr); *widgetPtr = widget; reappear(); connect(widget, &QWidget::destroyed, this, &LtsScreenContainer::slotChildDestroyed, Qt::UniqueConnection); if (tryPutDummyUnmanaged(widget)) return; m_layout->addWidget(widget); widget->show(); emit signalSetCornerIcons(); } void LtsScreenContainer::slotChildDestroyed() { if (sender() == static_cast(m_mainWidget)) { m_mainWidget = nullptr; qWarning() << geoStr() << "m_mainWidget set to nullptr!"; if (*m_activeWidget == m_mainWidget) { qWarning() << "slotChildDestroyed: switching to sec"; switchToTemp(LtsScreenBase::WidgetType::SecondaryWidget); QWidget *widget = activeWidget(); if (widget != nullptr) { auto *dummy = qobject_cast(widget); if (dummy != nullptr) { QRect r(mapToGlobal(rect().topLeft()), rect().size()); qWarning() << geoStr() << "LtsScreenContainer::slotChildDestroyed => (main) dummy->signalWidgetPlaced"; emit dummy->signalWidgetPlaced(r); } else { widget->show(); } } finalizeSwitch(); } } else if (sender() == static_cast(m_secondaryWidget)) { m_secondaryWidget = nullptr; qWarning() << geoStr() << "m_secondaryWidget set to nullptr!"; if (*m_activeWidget == m_secondaryWidget) { qWarning() << "slotChildDestroyed: switching to main"; switchToTemp(LtsScreenBase::WidgetType::MainWidget); QWidget *widget = activeWidget(); if (widget != nullptr) { auto *dummy = qobject_cast(widget); if (dummy != nullptr) { QRect r(mapToGlobal(rect().topLeft()), rect().size()); qWarning() << geoStr() << "LtsScreenContainer::slotChildDestroyed => (sec) dummy->signalWidgetPlaced"; emit dummy->signalWidgetPlaced(r); } else { widget->show(); } } finalizeSwitch(); } } else { qWarning() << geoStr() << "slotChildDestroyed NOT received from any known widget !!"; Q_ASSERT(false); } vanish(); emit check(); } QWidget *LtsScreenContainer::widget() noexcept(false) { QWidget **widgetPtr = m_activeWidget; if (widgetPtr != nullptr && *widgetPtr != nullptr) return *widgetPtr; throw "no widget in container"; } }