From f49aedfb8ac3cfa80a865551ae64d41895852035 Mon Sep 17 00:00:00 2001 From: audoban Date: Wed, 28 Dec 2016 02:57:31 -0500 Subject: [PATCH] XWindowInterface has been implemented --- corona/xwindowinterface.cpp | 395 ++++++++---------------------------- corona/xwindowinterface.h | 51 ++--- 2 files changed, 93 insertions(+), 353 deletions(-) diff --git a/corona/xwindowinterface.cpp b/corona/xwindowinterface.cpp index 530695c21..37d712e9c 100644 --- a/corona/xwindowinterface.cpp +++ b/corona/xwindowinterface.cpp @@ -1,361 +1,124 @@ #include "xwindowinterface.h" -#include +#include -#include #include +#include -namespace NowDock { +namespace Latte { -XWindowInterface::XWindowInterface(QQuickWindow *parent) : - AbstractInterface(parent), - m_demandsAttention(0) +XWindowInterface::XWindowInterface(QQuickWindow *const view, QObject *parent) + : AbstractWindowInterface(view, parent) { - m_activeWindow = KWindowSystem::activeWindow(); + Q_ASSERT(view != nullptr); - connect(KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)), this, SLOT(activeWindowChanged(WId))); - connect(KWindowSystem::self(), SIGNAL(windowChanged(WId, NET::Properties, NET::Properties2)), this, SLOT(windowChanged(WId, NET::Properties, NET::Properties2))); - connect(KWindowSystem::self(), SIGNAL(windowRemoved(WId)), this, SLOT(windowRemoved(WId))); + connect(KWindowSystem::self(), &KWindowSystem::activeWindowChanged + , this, &AbstractWindowInterface::activeWindowChanged); + + connect(KWindowSystem::self() + , static_cast + (&KWindowSystem::windowChanged) + , this, &XWindowInterface::windowChangedProxy); + + connect(KWindowSystem::self(), &KWindowSystem::windowAdded, [this](WId wid) { + if (std::find(m_windows.cbegin(), m_windows.cend(), wid) != m_windows.cend()) { + m_windows.push_back(wid); + } + + emit windowAdded(wid); + }); + + connect(KWindowSystem::self(), &KWindowSystem::windowAdded, [this](WId wid) { + m_windows.remove(wid); + emit windowRemoved(wid); + }); - connect(this, SIGNAL(dockNumberChanged(uint)), this, SLOT(dockNumberChanged(uint))); + connect(KWindowSystem::self(), &KWindowSystem::currentDesktopChanged + , this, &AbstractWindowInterface::currentDesktopChanged); } XWindowInterface::~XWindowInterface() { -} -void XWindowInterface::dockNumberChanged(unsigned int no) -{ - if (no == 1) { - m_dockWindow->setFlags(Qt::Tool | Qt::WindowDoesNotAcceptFocus | Qt::FramelessWindowHint); - } } -void XWindowInterface::setDockToAllDesktops() +void XWindowInterface::setDockDefaultFlags() { - KWindowSystem::setOnAllDesktops(m_dockWindow->winId(), true); + NETWinInfo winfo(QX11Info::connection() + , static_cast(m_view->winId()) + , static_cast(m_view->winId()) + , 0, 0); + + winfo.setAllowedActions(NET::ActionChangeDesktop); + KWindowSystem::setType(m_view->winId(), NET::Dock); + KWindowSystem::setOnAllDesktops(m_view->winId(), true); } -void XWindowInterface::setDockDefaultFlags(bool dock) +WId XWindowInterface::activeWindow() const { - //Notice: the Qt::Tool flag even though it works perfectly for a single Now Dock - //it creates a strange situation when there are two and more Now Dock's - //in that case it is used only for the first created Now Dock - m_isDockWindowType = dock; - - if ((m_dockNumber == 1) && (!m_isDockWindowType)) { - m_dockWindow->setFlags(Qt::Tool | Qt::WindowDoesNotAcceptFocus | Qt::FramelessWindowHint); - } else { - KWindowSystem::setType(m_dockWindow->winId(), NET::Dock); - KWindowSystem::setState(m_dockWindow->winId(), NET::SkipTaskbar | NET::SkipPager); - } + return KWindowSystem::self()->activeWindow(); } -void XWindowInterface::showDockOnTop() +const std::list &XWindowInterface::windows() { - //this is the only way in order to not break the case of two and more NowDocks - //there is a small issue that the pop ups from locked plasmoids are opened - //on the maximum thickness - - //qDebug() << "Docknumber:" << m_dockNumber; - if (m_isDockWindowType) { - return; - } - - if (m_dockNumber != 1) { - KWindowSystem::setType(m_dockWindow->winId(), NET::Dock); - } - - KWindowSystem::clearState(m_dockWindow->winId(), NET::KeepBelow); - KWindowSystem::setState(m_dockWindow->winId(), NET::KeepAbove); + return m_windows; } -void XWindowInterface::showDockAsNormal() +WindowInfoWrap XWindowInterface::requestInfoActive() { - // qDebug() << "reached make normal..."; - if (m_isDockWindowType) { - return; - } - - if (m_dockNumber != 1) { - m_dockWindow->setFlags(Qt::Tool | Qt::WindowDoesNotAcceptFocus | Qt::FramelessWindowHint); - } - - KWindowSystem::clearState(m_dockWindow->winId(), NET::KeepAbove); - KWindowSystem::clearState(m_dockWindow->winId(), NET::KeepBelow); -} - -void XWindowInterface::showDockOnBottom() -{ - // qDebug() << "reached make bottom..."; - if (m_isDockWindowType) { - return; - } - - if (m_dockNumber != 1) { - m_dockWindow->setFlags(Qt::Tool | Qt::WindowDoesNotAcceptFocus | Qt::FramelessWindowHint); - } - - KWindowSystem::clearState(m_dockWindow->winId(), NET::KeepAbove); - KWindowSystem::setState(m_dockWindow->winId(), NET::KeepBelow); + return requestInfo(KWindowSystem::activeWindow()); } - -bool XWindowInterface::isDesktop(WId id) const +WindowInfoWrap XWindowInterface::requestInfo(WId wid) { - KWindowInfo info(id, NET::WMWindowType); - - if (!info.valid()) { - return false; - } + const KWindowInfo winfo{wid, NET::WMDesktop | NET::WMFrameExtents | NET::WMWindowType | NET::WMState}; - NET::WindowType type = info.windowType(NET::DesktopMask | NET::DockMask | NET::DialogMask); - - return type == NET::Desktop; -} - -bool XWindowInterface::isDialog(WId id) const -{ - KWindowInfo info(id, NET::WMWindowType); + WindowInfoWrap winfoWrap; - if (!info.valid()) { - return false; - } - - NET::WindowType type = info.windowType(NET::DesktopMask | NET::DockMask | NET::DialogMask); - - return type == NET::Dialog; -} - -bool XWindowInterface::isMaximized(WId id) const -{ - KWindowInfo info(id, NET::WMState); - - if (!info.valid()) { - return false; - } - - return (info.hasState(NET::Max)); -} - -bool XWindowInterface::isNormal(WId id) const -{ - return (!isOnBottom(id) && !isOnTop(id)); -} - -bool XWindowInterface::isOnBottom(WId id) const -{ - KWindowInfo info(id, NET::WMState); - - if (!info.valid()) { - return false; - } - - return (info.hasState(NET::KeepBelow)); -} - -bool XWindowInterface::isOnTop(WId id) const -{ - KWindowInfo info(id, NET::WMState); - - if (!info.valid()) { - return false; - } - - return (info.hasState(NET::KeepAbove)); -} - -bool XWindowInterface::activeIsDialog() const -{ - return isDialog(m_activeWindow); -} - -bool XWindowInterface::activeIsMaximized() const -{ - return isMaximized(m_activeWindow); -} - - -bool XWindowInterface::desktopIsActive() const -{ - return isDesktop(m_activeWindow); -} - -bool XWindowInterface::dockIsOnTop() const -{ - return isOnTop(m_dockWindow->winId()); - -} - -bool XWindowInterface::dockInNormalState() const -{ - return isNormal(m_dockWindow->winId()); -} - -bool XWindowInterface::dockIsBelow() const -{ - return isOnBottom(m_dockWindow->winId()); -} - -bool XWindowInterface::dockIntersectsActiveWindow() const -{ - KWindowInfo activeInfo(m_activeWindow, NET::WMGeometry); - - if (activeInfo.valid()) { - QRect maskSize; - - if (!m_maskArea.isNull()) { - maskSize = QRect(m_dockWindow->x() + m_maskArea.x(), m_dockWindow->y() + m_maskArea.y(), m_maskArea.width(), m_maskArea.height()); - } else { - maskSize = QRect(m_dockWindow->x(), m_dockWindow->y(), m_dockWindow->width(), m_dockWindow->height()); - } + if (!winfo.valid() || !isValidWindow(winfo)) + return winfoWrap; - return maskSize.intersects(activeInfo.geometry()); - } else { + winfoWrap.setIsValid(true); + winfoWrap.setWid(wid); + winfoWrap.setIsActive(KWindowSystem::activeWindow() == wid); + winfoWrap.setIsMinimized(winfo.hasState(NET::Hidden)); + winfoWrap.setIsMaximized(winfo.hasState(NET::Max)); + winfoWrap.setIsFullscreen(winfo.hasState(NET::FullScreen)); + winfoWrap.setIsOnCurrentDesktop(winfo.isOnCurrentDesktop()); + winfoWrap.setGeometry(winfo.geometry()); + + return winfoWrap; +} + +bool XWindowInterface::isValidWindow(const KWindowInfo &winfo) +{ + const auto winType = winfo.windowType(NET::DesktopMask | NET::DockMask + | NET::MenuMask | NET::SplashMask + | NET::NormalMask); + + if (winType == -1 || (winType & NET::Desktop) || (winType & NET::Menu) + || (winType & NET::Dock) || (winType & NET::Splash)) { return false; } -} - - -bool XWindowInterface::dockIsCovered(bool totally) const -{ - int currentDockPos = -1; - - QList windows = KWindowSystem::stackingOrder(); - int size = windows.count(); - - for (int i = size - 1; i >= 0; --i) { - WId window = windows.at(i); - - if (window == m_dockWindow->winId()) { - currentDockPos = i; - break; - } - } - - if (currentDockPos >= 0) { - QRect maskSize; - - if (!m_maskArea.isNull()) { - maskSize = QRect(m_dockWindow->x() + m_maskArea.x(), m_dockWindow->y() + m_maskArea.y(), m_maskArea.width(), m_maskArea.height()); - } else { - maskSize = QRect(m_dockWindow->x(), m_dockWindow->y(), m_dockWindow->width(), m_dockWindow->height()); - } - - WId transient = 0; - - if (m_dockWindow->transientParent()) { - transient = m_dockWindow->transientParent()->winId(); - } - - for (int j = size - 1; j > currentDockPos; --j) { - WId window = windows.at(j); - - KWindowInfo info(window, NET::WMState | NET::XAWMState | NET::WMGeometry); - - if (info.valid() && !isDesktop(window) && transient != window && !info.isMinimized()) { - if (totally) { - QRect winGeometry = info.geometry(); - - if ((maskSize.left() >= winGeometry.left()) && (maskSize.top() >= winGeometry.top()) - && (maskSize.right() <= winGeometry.right()) && (maskSize.bottom() <= winGeometry.bottom())) { - return true; - } - } else { - if (maskSize.intersects(info.geometry())) { - return true; - } - } - } - } - } - return false; + return true; } -bool XWindowInterface::dockIsCovering() const +void XWindowInterface::windowChangedProxy(WId wid, NET::Properties prop1, NET::Properties2 prop2) { - int currentDockPos = -1; - - QList windows = KWindowSystem::stackingOrder(); - int size = windows.count(); - - for (int i = size - 1; i >= 0; --i) { - WId window = windows.at(i); - - if (window == m_dockWindow->winId()) { - currentDockPos = i; - break; - } - } - - if (currentDockPos >= 0) { - QRect maskSize; - - if (!m_maskArea.isNull()) { - maskSize = QRect(m_dockWindow->x() + m_maskArea.x(), m_dockWindow->y() + m_maskArea.y(), m_maskArea.width(), m_maskArea.height()); - } else { - maskSize = QRect(m_dockWindow->x(), m_dockWindow->y(), m_dockWindow->width(), m_dockWindow->height()); - } + //! if the dock changed is ignored + if (wid == m_view->winId()) + return; - WId transient = 0; + //! ignore when, eg: the user presses a key + if (prop1 == 0 && prop2 == NET::WM2UserTime) + return; - if (m_dockWindow->transientParent()) { - transient = m_dockWindow->transientParent()->winId(); - } + if (prop1 && !(prop1 & NET::WMState || prop1 & NET::WMGeometry || prop1 & NET::ActiveWindow)) + return; - for (int j = currentDockPos - 1; j >= 0; --j) { - WId window = windows.at(j); - - KWindowInfo info(window, NET::WMState | NET::XAWMState | NET::WMGeometry); - - if (info.valid() && !isDesktop(window) && transient != window && !info.isMinimized() && maskSize.intersects(info.geometry())) { - return true; - } - } - } - - return false; -} - -/* - * SLOTS - */ - -void XWindowInterface::activeWindowChanged(WId win) -{ - m_activeWindow = win; - - emit AbstractInterface::activeWindowChanged(); -} - -void XWindowInterface::windowChanged(WId id, NET::Properties properties, NET::Properties2 properties2) -{ - KWindowInfo info(id, NET::WMState | NET::CloseWindow); - - if (info.valid()) { - if ((m_demandsAttention == 0) && info.hasState(NET::DemandsAttention)) { - m_demandsAttention = id; - emit windowInAttention(true); - } else if ((m_demandsAttention == id) && !info.hasState(NET::DemandsAttention)) { - m_demandsAttention = 0; - emit windowInAttention(false); - } - } - - // emit AbstractInterface::windowChanged(); - - if (id == m_activeWindow) { - emit AbstractInterface::activeWindowChanged(); - } + emit windowChanged(requestInfo(wid)); } -void XWindowInterface::windowRemoved(WId id) -{ - if (id == m_demandsAttention) { - m_demandsAttention = 0; - emit AbstractInterface::windowInAttention(false); - } } -} diff --git a/corona/xwindowinterface.h b/corona/xwindowinterface.h index 178687e77..4fd3f51d9 100644 --- a/corona/xwindowinterface.h +++ b/corona/xwindowinterface.h @@ -1,59 +1,36 @@ -#ifndef XWINDOWINTERFACE_H +#ifndef XWINDOWINTERFACE_H #define XWINDOWINTERFACE_H #include #include -#include "abstractinterface.h" +#include "abstractwindowinterface.h" -namespace NowDock { +namespace Latte { -class XWindowInterface : public AbstractInterface { +class XWindowInterface : public AbstractWindowInterface { Q_OBJECT public: - explicit XWindowInterface(QQuickWindow *parent); - ~XWindowInterface(); + XWindowInterface(QQuickWindow *const view, QObject *parent); + virtual ~XWindowInterface(); - bool activeIsDialog() const; - bool activeIsMaximized() const; - bool dockIntersectsActiveWindow() const; - bool desktopIsActive() const; - bool dockIsCovered(bool totally = false) const; - bool dockIsCovering() const; - bool dockIsOnTop() const; - bool dockInNormalState() const; - bool dockIsBelow() const; + void setDockDefaultFlags() override; - void setDockDefaultFlags(bool dock = false); - void setDockToAllDesktops(); - void setDockToAlwaysVisible(); - void showDockAsNormal(); - void showDockOnBottom(); - void showDockOnTop(); - -private Q_SLOTS: - void activeWindowChanged(WId win); - void dockNumberChanged(unsigned int no); - void windowChanged(WId id, NET::Properties properties, NET::Properties2 properties2); - void windowRemoved(WId id); + WId activeWindow() const override; + WindowInfoWrap requestInfo(WId wid) override; + WindowInfoWrap requestInfoActive() override; + const std::list &windows() override; private: - WId m_activeWindow; - WId m_demandsAttention; - - bool isDesktop(WId id) const; - bool isDialog(WId id) const; - bool isMaximized(WId id) const; - bool isNormal(WId id) const; - bool isOnBottom(WId id) const; - bool isOnTop(WId id) const; + bool isValidWindow(const KWindowInfo &winfo); + void windowChangedProxy(WId wid, NET::Properties prop1, NET::Properties2 prop2); }; } -#endif +#endif // XWINDOWINTERFACE_H