diff --git a/CMakeLists.txt b/CMakeLists.txt index a36765cdd..7c4f6c02e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ set_package_properties(X11 PROPERTIES DESCRIPTION "X11 libraries" PURPOSE "Required for building the X11 based workspace") if(X11_FOUND) - find_package(XCB MODULE REQUIRED COMPONENTS XCB) + find_package(XCB MODULE REQUIRED COMPONENTS XCB RANDR) set_package_properties(XCB PROPERTIES TYPE REQUIRED) find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS X11Extras) endif() diff --git a/app/dockcorona.cpp b/app/dockcorona.cpp index c6fb0548b..ba13dd414 100644 --- a/app/dockcorona.cpp +++ b/app/dockcorona.cpp @@ -26,8 +26,10 @@ #include "screenpool.h" #include +#include #include #include +#include #include #include @@ -96,9 +98,11 @@ void DockCorona::load() m_activitiesStarting = false; - connect(qGuiApp, &QGuiApplication::screenAdded, this, &DockCorona::addOutput, Qt::UniqueConnection); + // connect(qGuiApp, &QGuiApplication::screenAdded, this, &DockCorona::addOutput, Qt::UniqueConnection); connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, &DockCorona::primaryOutputChanged, Qt::UniqueConnection); - connect(qGuiApp, &QGuiApplication::screenRemoved, this, &DockCorona::screenRemoved, Qt::UniqueConnection); + // connect(qGuiApp, &QGuiApplication::screenRemoved, this, &DockCorona::screenRemoved, Qt::UniqueConnection); + connect(QApplication::desktop(), &QDesktopWidget::screenCountChanged, this, &DockCorona::screenCountChanged); + connect(m_screenPool, &ScreenPool::primaryPoolChanged, this, &DockCorona::screenCountChanged); loadLayout(); } @@ -223,13 +227,13 @@ QRect DockCorona::availableScreenRect(int id) const // need calculate available space for top and bottom location, // because the left and right are those who dodge others docks switch (view->location()) { - case Plasma::Types::TopEdge: - available.setTopLeft({available.x(), dockRect.bottom()}); - break; + case Plasma::Types::TopEdge: + available.setTopLeft({available.x(), dockRect.bottom()}); + break; - case Plasma::Types::BottomEdge: - available.setBottomLeft({available.x(), dockRect.top()}); - break; + case Plasma::Types::BottomEdge: + available.setBottomLeft({available.x(), dockRect.top()}); + break; } } } @@ -240,15 +244,110 @@ QRect DockCorona::availableScreenRect(int id) const void DockCorona::addOutput(QScreen *screen) { Q_ASSERT(screen); + + /* qDebug() << "screen added +++ "<name(); + foreach(auto scr, qGuiApp->screens()){ + qDebug() << "Found screen: "<name(); + }*/ + + /* foreach(auto cont, containments()) { + if (m_screenPool->connector(cont->screen()) == screen->name()) { + auto view = m_dockViews.take(cont); + if (!view) { + addDock(cont); + } + } + } */ } void DockCorona::primaryOutputChanged() { + qDebug() << "primary changed ### "<< qGuiApp->primaryScreen()->name(); + foreach(auto scr, qGuiApp->screens()){ + qDebug() << "Found screen: "<name(); + } + + if (m_dockViews.count()==1 && qGuiApp->screens().size()==1) { + foreach(auto view, m_dockViews) { + view->setScreenToFollow(qGuiApp->primaryScreen()); + } + } } void DockCorona::screenRemoved(QScreen *screen) { Q_ASSERT(screen); + /* qDebug() << "screen removed --- "<name(); + foreach(auto scr, qGuiApp->screens()){ + qDebug() << "Found screen: "<name(); + }*/ + + /* if (m_dockViews.size() > 1) { + foreach(auto cont, containments()) { + if (m_screenPool->connector(cont->screen()) == screen->name()) { + auto view = m_dockViews.take(cont); + if (view) { + view->deleteLater(); + } + } + } + } */ +} + +void DockCorona::screenCountChanged() +{ + QTimer::singleShot(2500, this, &DockCorona::screenCountChangedTimer); +} + +void DockCorona::screenCountChangedTimer() +{ + qDebug() << "screen count changed -+-+ "<< qGuiApp->screens().size(); + + qDebug() << "adding consideration...."; + foreach(auto scr, qGuiApp->screens()){ + qDebug() << "Found screen: "<name(); + + foreach(auto cont, containments()) { + int id = cont->screen(); + + if (id == -1){ + id = cont->lastScreen(); + } + + if ((m_screenPool->connector(id) == scr->name()) && (!m_dockViews.contains(cont))) { + qDebug() << "screen Count signal: view must be added... for:"<< scr->name(); + addDock(cont); + } + } + } + + qDebug() << "removing consideration...."; + + foreach(auto view, m_dockViews){ + bool found{false}; + foreach(auto scr, qGuiApp->screens()){ + int id = view->containment()->screen(); + + if (id == -1){ + id = view->containment()->lastScreen(); + } + + if(scr->name() == view->currentScreen()){ + found = true; + break; + } + } + + if (!found && (m_dockViews.size()>1) && m_dockViews.contains(view->containment())) { + qDebug() << "screen Count signal: view must be deleted... for:"<currentScreen(); + auto viewToDelete = m_dockViews.take(view->containment()); + viewToDelete->deleteLater(); + } else { + view->reconsiderScreen(); + } + } + + qDebug() << "end of screens count change...."; } int DockCorona::primaryScreenId() const @@ -268,8 +367,8 @@ int DockCorona::docksCount(int screen) const for (const auto &view : m_dockViews) { if (view && view->containment() - && view->containment()->screen() == screen - && !view->containment()->destroyed()) { + && view->containment()->screen() == screen + && !view->containment()->destroyed()) { ++docks; } } @@ -301,13 +400,13 @@ QList DockCorona::freeEdges(int screen) const { using Plasma::Types; QList edges{Types::BottomEdge, Types::LeftEdge, - Types::TopEdge, Types::RightEdge}; + Types::TopEdge, Types::RightEdge}; //when screen=-1 is passed then the primaryScreenid is used int fixedScreen = (screen == -1) ? primaryScreenId() : screen; for (auto *view : m_dockViews) { if (view && view->containment() - && view->containment()->screen() == fixedScreen) { + && view->containment()->screen() == fixedScreen) { edges.removeOne(view->location()); } } @@ -349,13 +448,13 @@ int DockCorona::screenForContainment(const Plasma::Containment *containment) con //It is also correct for desktops *that have the correct activity()* //a containment with lastScreen() == 0 but another activity, //won't be associated to a screen -// qDebug() << "ShellCorona screenForContainment: " << containment << " Last screen is " << containment->lastScreen(); + // qDebug() << "ShellCorona screenForContainment: " << containment << " Last screen is " << containment->lastScreen(); for (auto screen : qGuiApp->screens()) { // containment->lastScreen() == m_screenPool->id(screen->name()) to check if the lastScreen refers to a screen that exists/it's known if (containment->lastScreen() == m_screenPool->id(screen->name()) && - (containment->activity() == m_activityConsumer->currentActivity() || - containment->containmentType() == Plasma::Types::PanelContainment || containment->containmentType() == Plasma::Types::CustomPanelContainment)) { + (containment->activity() == m_activityConsumer->currentActivity() || + containment->containmentType() == Plasma::Types::PanelContainment || containment->containmentType() == Plasma::Types::CustomPanelContainment)) { return containment->lastScreen(); } } @@ -384,8 +483,14 @@ void DockCorona::addDock(Plasma::Containment *containment) QScreen *nextScreen{qGuiApp->primaryScreen()}; - if (containment->screen() >= 0) { - QString connector = m_screenPool->connector(containment->screen()); + int id = containment->screen(); + + if (id == -1) { + id = containment->lastScreen(); + } + + if (id >= 0) { + QString connector = m_screenPool->connector(id); bool found{false}; foreach(auto scr, qGuiApp->screens()){ if (scr && scr->name() == connector){ @@ -417,6 +522,7 @@ void DockCorona::addDock(Plasma::Containment *containment) void DockCorona::destroyedChanged(bool destroyed) { + qDebug() << "dock containment destroyed changed!!!!"; Plasma::Containment *sender = qobject_cast(QObject::sender()); if (!sender) { @@ -434,6 +540,7 @@ void DockCorona::destroyedChanged(bool destroyed) void DockCorona::dockContainmentDestroyed(QObject *cont) { + qDebug() << "dock containment destroyed!!!!"; auto view = m_waitingDockViews.take(static_cast(cont)); if (view) diff --git a/app/dockcorona.h b/app/dockcorona.h index d6455ce3b..37a7651b6 100644 --- a/app/dockcorona.h +++ b/app/dockcorona.h @@ -84,6 +84,8 @@ private slots: void addOutput(QScreen *screen); void primaryOutputChanged(); void screenRemoved(QScreen *screen); + void screenCountChanged(); + void screenCountChangedTimer(); private: bool appletExists(uint containmentId, uint appletId) const; diff --git a/app/dockview.cpp b/app/dockview.cpp index d172d676d..39e85f17a 100644 --- a/app/dockview.cpp +++ b/app/dockview.cpp @@ -64,9 +64,11 @@ DockView::DockView(Plasma::Corona *corona, QScreen *targetScreen) setScreenToFollow(qGuiApp->primaryScreen()); connect(this, &DockView::containmentChanged - , this, [&]() { + , this, [&]() { + qDebug() << "entered creating step 1..."; if (!this->containment()) return; + qDebug() << "entered creating step 2..."; if (!m_visibility) { m_visibility = new VisibilityManager(this); @@ -114,7 +116,8 @@ void DockView::init() { connect(this, &QQuickWindow::screenChanged, this, &DockView::screenChanged); - connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, &DockView::syncGeometry, Qt::UniqueConnection); + connect(qGuiApp, &QGuiApplication::screenAdded, this, &DockView::reconsiderScreen); + connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, &DockView::reconsiderScreen); connect(this, &DockView::screenGeometryChanged, this, &DockView::syncGeometry); connect(this, &QQuickWindow::widthChanged, this, &DockView::widthChanged); connect(this, &QQuickWindow::heightChanged, this, &DockView::heightChanged); @@ -140,7 +143,7 @@ void DockView::init() void DockView::adaptToScreen(QScreen *screen) { -/* if (!screen) { + /* if (!screen) { return; } @@ -183,6 +186,7 @@ void DockView::setScreenToFollow(QScreen *screen) } m_screenToFollow = screen; + m_screenToFollowId = screen->name(); qDebug() << "adapting to screen..."; @@ -194,18 +198,51 @@ void DockView::setScreenToFollow(QScreen *screen) syncGeometry(); } +void DockView::reconsiderScreen() +{ + qDebug() << " Delayer "; + foreach(auto scr, qGuiApp->screens()){ + qDebug() << " D, found screen: "<name(); + } + + foreach(auto scr, qGuiApp->screens()){ + if (scr && scr->name() == m_screenToFollowId){ + setScreenToFollow(scr); + syncGeometry(); + } + } + + emit docksCountChanged(); +} + void DockView::screenChanged(QScreen *scr) { if (!scr || m_screenToFollow == scr) { return; } - emit docksCountChanged(); + qDebug() << "Screen inconsistency!!! :" << scr->name() << " - " <name(); + QTimer::singleShot(2500, this, &DockView::reconsiderScreen); + + /*bool found{false}; + foreach(auto scr, qGuiApp->screens()){ + qDebug() << "Found screen: "<name(); + if (scr && scr == m_screenToFollow){ + found=true; + //break; + } + } + + + + if (found) { + //IMPORTAT!!! this code creates crashes when changing plasma + //layouts it needs inverstigation!!! + setScreen(m_screenToFollow); + syncGeometry(); + }*/ + // emit docksCountChanged(); - //IMPORTAT!!! this code creates crashes when changing plasma - //layouts it needs inverstigation!!! - // setScreen(m_screenToFollow); - // syncGeometry(); } void DockView::addNewDock() @@ -247,10 +284,7 @@ QScreen *DockView::atScreens(QQmlListProperty *property, int index) QString DockView::currentScreen() const { - if (m_screenToFollow) - return m_screenToFollow->name(); - - return ""; + return m_screenToFollowId; } void DockView::showConfigurationInterface(Plasma::Applet *applet) @@ -340,7 +374,7 @@ void DockView::setLocalDockGeometry(const QRect &geometry) void DockView::updateAbsDockGeometry(const QRect &localDockGeometry) { QRect absGeometry {x() + localDockGeometry.x(), y() + localDockGeometry.y() - , localDockGeometry.width() - 1, localDockGeometry.height() - 1}; + , localDockGeometry.width() - 1, localDockGeometry.height() - 1}; if (m_absGeometry == absGeometry) return; @@ -363,58 +397,58 @@ void DockView::updatePosition() int cleanThickness = normalThickness() - shadow(); switch (location()) { - case Plasma::Types::TopEdge: - screenGeometry = this->screen()->geometry(); + case Plasma::Types::TopEdge: + screenGeometry = this->screen()->geometry(); - if (m_drawShadows) { - position = {screenGeometry.x() + length(screenGeometry.width()), screenGeometry.y()}; - } else { - position = {screenGeometry.x(), screenGeometry.y()}; - } + if (m_drawShadows) { + position = {screenGeometry.x() + length(screenGeometry.width()), screenGeometry.y()}; + } else { + position = {screenGeometry.x(), screenGeometry.y()}; + } - break; + break; - case Plasma::Types::BottomEdge: - screenGeometry = this->screen()->geometry(); - qDebug() << "screen geometry: "<screen()->geometry(); + qDebug() << "screen geometry: "<availableScreenRect(this->containment()->screen()); + case Plasma::Types::RightEdge: + screenGeometry = corona()->availableScreenRect(this->containment()->screen()); - if (m_drawShadows && !mask().isNull()) { - position = {screenGeometry.x() + screenGeometry.width() - cleanThickness, - screenGeometry.y() + length(screenGeometry.height()) - }; - } else { - position = {screenGeometry.x() + screenGeometry.width() - width(), screenGeometry.y()}; - } + if (m_drawShadows && !mask().isNull()) { + position = {screenGeometry.x() + screenGeometry.width() - cleanThickness, + screenGeometry.y() + length(screenGeometry.height()) + }; + } else { + position = {screenGeometry.x() + screenGeometry.width() - width(), screenGeometry.y()}; + } - break; + break; - case Plasma::Types::LeftEdge: - screenGeometry = corona()->availableScreenRect(this->containment()->screen()); + case Plasma::Types::LeftEdge: + screenGeometry = corona()->availableScreenRect(this->containment()->screen()); - if (m_drawShadows && !mask().isNull()) { - position = {screenGeometry.x(), screenGeometry.y() + length(screenGeometry.height())}; - } else { - position = {screenGeometry.x(), screenGeometry.y()}; - } + if (m_drawShadows && !mask().isNull()) { + position = {screenGeometry.x(), screenGeometry.y() + length(screenGeometry.height())}; + } else { + position = {screenGeometry.x(), screenGeometry.y()}; + } - break; + break; - default: - qWarning() << "wrong location, couldn't update the panel position" - << location(); + default: + qWarning() << "wrong location, couldn't update the panel position" + << location(); } setPosition(position); @@ -428,13 +462,30 @@ inline void DockView::syncGeometry() //if (qGuiApp->primaryScreen() && screen() != qGuiApp->primaryScreen()){ // setScreen(qGuiApp->primaryScreen()); //} - if (screen() != m_screenToFollow) { - setScreenToFollow(m_screenToFollow); + bool found{false}; + if (this->screen() != m_screenToFollow) { + qDebug() << "Sync Geometry screens incosistent!!!!"; + foreach(auto scr, qGuiApp->screens()){ + qDebug() << "Found screen: "<name(); + if (scr && scr->name() == m_screenToFollowId){ + qDebug() << " found ... "; + //setScreenToFollow(scr); + // found=true; + } + } + QTimer::singleShot(2500, this, &DockView::reconsiderScreen); + + //if (found) + // setScreenToFollow(m_screenToFollow); + } else { + found = true; } - updateEnabledBorders(); - resizeWindow(); - updatePosition(); + if (found) { + updateEnabledBorders(); + resizeWindow(); + updatePosition(); + } // qDebug() << "dock geometry:" << qRectToStr(geometry()); } @@ -442,7 +493,7 @@ void DockView::statusChanged(Plasma::Types::ItemStatus status) { if (containment()) { if (containment()->status() >= Plasma::Types::NeedsAttentionStatus && - containment()->status() != Plasma::Types::HiddenStatus) { + containment()->status() != Plasma::Types::HiddenStatus) { m_visibility->setBlockHiding(true); } else { m_visibility->setBlockHiding(false); @@ -491,18 +542,18 @@ void DockView::updateFormFactor() return; switch (location()) { - case Plasma::Types::TopEdge: - case Plasma::Types::BottomEdge: - this->containment()->setFormFactor(Plasma::Types::Horizontal); - break; - - case Plasma::Types::LeftEdge: - case Plasma::Types::RightEdge: - this->containment()->setFormFactor(Plasma::Types::Vertical); - break; - - default: - qWarning() << "wrong location, couldn't update the panel position" << location(); + case Plasma::Types::TopEdge: + case Plasma::Types::BottomEdge: + this->containment()->setFormFactor(Plasma::Types::Horizontal); + break; + + case Plasma::Types::LeftEdge: + case Plasma::Types::RightEdge: + this->containment()->setFormFactor(Plasma::Types::Vertical); + break; + + default: + qWarning() << "wrong location, couldn't update the panel position" << location(); } } @@ -958,7 +1009,7 @@ void DockView::addAppletActions(QMenu *desktopMenu, Plasma::Applet *applet, QEve } if (this->containment()->immutability() == Plasma::Types::Mutable && - (this->containment()->containmentType() != Plasma::Types::PanelContainment || this->containment()->isUserConfiguring())) { + (this->containment()->containmentType() != Plasma::Types::PanelContainment || this->containment()->isUserConfiguring())) { QAction *closeApplet = applet->actions()->action(QStringLiteral("remove")); //qDebug() << "checking for removal" << closeApplet; @@ -980,7 +1031,7 @@ void DockView::addContainmentActions(QMenu *desktopMenu, QEvent *event) } if (this->containment()->corona()->immutability() != Plasma::Types::Mutable && - !KAuthorized::authorizeAction(QStringLiteral("plasma/containment_actions"))) { + !KAuthorized::authorizeAction(QStringLiteral("plasma/containment_actions"))) { //qDebug() << "immutability"; return; } @@ -1010,7 +1061,7 @@ void DockView::addContainmentActions(QMenu *desktopMenu, QEvent *event) //a better plugin. note that if the user sets no-plugin this won't happen... if ((this->containment()->containmentType() != Plasma::Types::PanelContainment && this->containment()->containmentType() != Plasma::Types::CustomPanelContainment) && - this->containment()->actions()->action(QStringLiteral("configure"))) { + this->containment()->actions()->action(QStringLiteral("configure"))) { desktopMenu->addAction(this->containment()->actions()->action(QStringLiteral("configure"))); } } else { @@ -1050,24 +1101,24 @@ void DockView::updateEnabledBorders() Plasma::FrameSvg::EnabledBorders borders = Plasma::FrameSvg::AllBorders; switch (location()) { - case Plasma::Types::TopEdge: - borders &= ~Plasma::FrameSvg::TopBorder; - break; + case Plasma::Types::TopEdge: + borders &= ~Plasma::FrameSvg::TopBorder; + break; - case Plasma::Types::LeftEdge: - borders &= ~Plasma::FrameSvg::LeftBorder; - break; + case Plasma::Types::LeftEdge: + borders &= ~Plasma::FrameSvg::LeftBorder; + break; - case Plasma::Types::RightEdge: - borders &= ~Plasma::FrameSvg::RightBorder; - break; + case Plasma::Types::RightEdge: + borders &= ~Plasma::FrameSvg::RightBorder; + break; - case Plasma::Types::BottomEdge: - borders &= ~Plasma::FrameSvg::BottomBorder; - break; + case Plasma::Types::BottomEdge: + borders &= ~Plasma::FrameSvg::BottomBorder; + break; - default: - break; + default: + break; } if ((location() == Plasma::Types::LeftEdge || location() == Plasma::Types::RightEdge)) { diff --git a/app/dockview.h b/app/dockview.h index 113aa27de..9ff752bed 100644 --- a/app/dockview.h +++ b/app/dockview.h @@ -112,6 +112,7 @@ public: QQmlListProperty screens(); static int countScreens(QQmlListProperty *property); static QScreen *atScreens(QQmlListProperty *property, int index); + void reconsiderScreen(); public slots: Q_INVOKABLE void addNewDock(); @@ -184,6 +185,7 @@ private: QPointer m_configView; QPointer m_visibility; QPointer m_screenToFollow; + QString m_screenToFollowId; //only for the mask, not to actually paint Plasma::FrameSvg::EnabledBorders m_enabledBorders = Plasma::FrameSvg::AllBorders; diff --git a/app/screenpool.cpp b/app/screenpool.cpp index 1fd22b137..25a9d8e62 100644 --- a/app/screenpool.cpp +++ b/app/screenpool.cpp @@ -18,16 +18,26 @@ */ #include "screenpool.h" +#include #include #include +#if HAVE_X11 +#include +#include +#include +#include +#endif + ScreenPool::ScreenPool(KSharedConfig::Ptr config, QObject *parent) : QObject(parent), m_configGroup(KConfigGroup(config, QStringLiteral("ScreenConnectors"))) { + qApp->installNativeEventFilter(this); + m_configSaveTimer.setSingleShot(true); - connect(&m_configSaveTimer, &QTimer::timeout, this, [this]() { + connect(&m_configSaveTimer, &QTimer::timeout, this, [this](){ m_configGroup.sync(); }); } @@ -39,10 +49,8 @@ void ScreenPool::load() m_idForConnector.clear(); QScreen *primary = qGuiApp->primaryScreen(); - if (primary) { m_primaryConnector = primary->name(); - if (!m_primaryConnector.isEmpty()) { m_connectorForId[0] = m_primaryConnector; m_idForConnector[m_primaryConnector] = 0; @@ -52,7 +60,6 @@ void ScreenPool::load() //restore the known ids to connector mappings foreach (const QString &key, m_configGroup.keyList()) { QString connector = m_configGroup.readEntry(key, QString()); - if (!key.isEmpty() && !connector.isEmpty() && !m_connectorForId.contains(key.toInt()) && !m_idForConnector.contains(connector)) { @@ -68,7 +75,7 @@ void ScreenPool::load() // containment->screen() will return an incorrect -1 // at startup, if it' asked before corona::addOutput() // is performed, driving to the creation of a new containment - for (QScreen *screen : qGuiApp->screens()) { + for (QScreen* screen : qGuiApp->screens()) { if (!m_idForConnector.contains(screen->name())) { insertScreenMapping(firstAvailableId(), screen->name()); } @@ -90,7 +97,6 @@ void ScreenPool::setPrimaryConnector(const QString &primary) if (m_primaryConnector == primary) { return; } - Q_ASSERT(m_idForConnector.contains(primary)); int oldIdForPrimary = m_idForConnector.value(primary); @@ -106,11 +112,9 @@ void ScreenPool::setPrimaryConnector(const QString &primary) void ScreenPool::save() { QMap::const_iterator i; - for (i = m_connectorForId.constBegin(); i != m_connectorForId.constEnd(); ++i) { m_configGroup.writeEntry(QString::number(i.key()), i.value()); } - //write to disck every 30 seconds at most m_configSaveTimer.start(30000); } @@ -148,14 +152,12 @@ QString ScreenPool::connector(int id) const int ScreenPool::firstAvailableId() const { int i = 0; - //find the first integer not stored in m_connectorForId //m_connectorForId is the only map, so the ids are sorted foreach (int existingId, m_connectorForId.keys()) { if (i != existingId) { return i; } - ++i; } @@ -167,4 +169,39 @@ QList ScreenPool::knownIds() const return m_connectorForId.keys(); } +bool ScreenPool::nativeEventFilter(const QByteArray& eventType, void* message, long int* result) +{ + Q_UNUSED(result); +#if HAVE_X11 + // a particular edge case: when we switch the only enabled screen + // we don't have any signal about it, the primary screen changes but we have the same old QScreen* getting recycled + // see https://bugs.kde.org/show_bug.cgi?id=373880 + // if this slot will be invoked many times, their//second time on will do nothing as name and primaryconnector will be the same by then + if (eventType != "xcb_generic_event_t") { + return false; + } + + xcb_generic_event_t *ev = static_cast(message); + + const auto responseType = XCB_EVENT_RESPONSE_TYPE(ev); + + const xcb_query_extension_reply_t* reply = xcb_get_extension_data(QX11Info::connection(), &xcb_randr_id); + + if (responseType == reply->first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY) { + if (qGuiApp->primaryScreen()->name() != primaryConnector()) { + //new screen? + if (id(qGuiApp->primaryScreen()->name()) < 0) { + insertScreenMapping(firstAvailableId(), qGuiApp->primaryScreen()->name()); + } + //switch the primary screen in the pool + setPrimaryConnector(qGuiApp->primaryScreen()->name()); + + emit primaryPoolChanged(); + } + } +#endif + return false; +} + + #include "moc_screenpool.cpp" diff --git a/app/screenpool.h b/app/screenpool.h index 9b3a9af42..ac33d1ed8 100644 --- a/app/screenpool.h +++ b/app/screenpool.h @@ -24,11 +24,13 @@ #include #include #include +#include #include #include -class ScreenPool : public QObject { +class ScreenPool : public QObject, public QAbstractNativeEventFilter +{ Q_OBJECT public: @@ -50,6 +52,12 @@ public: //all ids that are known, included screens not enabled at the moment QList knownIds() const; +signals: + void primaryPoolChanged(); + +protected: + bool nativeEventFilter(const QByteArray & eventType, void * message, long * result) Q_DECL_OVERRIDE; + private: void save();