From 6010638094af4410ff3a1e3f5d79e618cbfb4fe7 Mon Sep 17 00:00:00 2001 From: Michail Vourlakos Date: Thu, 2 Mar 2017 22:10:26 +0200 Subject: [PATCH] support overlap dock cases by using free space --this commit uses free region from corona instead of free rectangle in order to calculate size and positioning for the docks. This way is possible to be positioned more intelligently. --- app/dockcorona.cpp | 100 ++++++++++++++++++++++++++++++++++++++++++-- app/dockview.cpp | 101 ++++++++++++++++++++++++++++++++++++++++----- app/dockview.h | 2 + 3 files changed, 189 insertions(+), 14 deletions(-) diff --git a/app/dockcorona.cpp b/app/dockcorona.cpp index 7bb7cbb69..5763d795a 100644 --- a/app/dockcorona.cpp +++ b/app/dockcorona.cpp @@ -205,10 +205,102 @@ QRect DockCorona::screenGeometry(int id) const QRegion DockCorona::availableScreenRegion(int id) const { - return availableScreenRect(id); - //FIXME::: availableGeometry is probably broken - // in Qt, so this have to be updated as plasma is doing it - // for example the availableScreenRect + const auto screens = qGuiApp->screens(); + const QScreen *screen{qGuiApp->primaryScreen()}; + QString scrName = m_screenPool->connector(id); + + foreach (auto scr, screens) { + if (scr->name() == scrName) { + screen = scr; + break; + } + } + + if (!screen) + return QRegion(); + + QRegion available(screen->geometry()); + + for (const auto *view : m_dockViews) { + if (view && view->containment() && view->screen() == screen) { + int realThickness = view->normalThickness() - view->shadow(); + + // Usually availableScreenRect is used by the desktop, + // but Latte dont have desktop, then here just + // 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: + if (view->drawShadows()) { + available -= view->geometry(); + } else { + QRect realGeometry; + int realWidth = view->maxLength() * view->width(); + + switch (view->alignment()) { + case Latte::Dock::Left: + realGeometry = QRect(view->x(), view->y(), + realWidth, realThickness); + break; + + case Latte::Dock::Center: + case Latte::Dock::Justify: + realGeometry = QRect(view->geometry().center().x() - realWidth / 2 , view->y(), + realWidth , realThickness); + break; + + case Latte::Dock::Right: + realGeometry = QRect(view->geometry().right() - realWidth + 1, view->y(), + realWidth, realThickness); + break; + } + + available -= realGeometry; + } + + break; + + case Plasma::Types::BottomEdge: + if (view->drawShadows()) { + available -= view->geometry(); + } else { + QRect realGeometry; + int realWidth = view->maxLength() * view->width(); + int realY = view->geometry().bottom() - realThickness + 1; + + switch (view->alignment()) { + case Latte::Dock::Left: + realGeometry = QRect(view->x(), realY, + realWidth, realThickness); + break; + + case Latte::Dock::Center: + case Latte::Dock::Justify: + realGeometry = QRect(qMax(view->geometry().x(), view->geometry().center().x() - realWidth / 2), + realY, realWidth, realThickness); + break; + + case Latte::Dock::Right: + realGeometry = QRect(view->geometry().right() - realWidth + 1, realY, + realWidth, realThickness); + break; + } + + available -= realGeometry; + } + + break; + } + } + } + + /*qDebug() << "::::: FREE AREAS :::::"; + for (int i = 0; i < available.rectCount(); ++i) { + qDebug() << available.rects().at(i); + } + qDebug() << "::::: END OF FREE AREAS :::::";*/ + + return available; } QRect DockCorona::availableScreenRect(int id) const diff --git a/app/dockview.cpp b/app/dockview.cpp index 2231e62ca..b550816cf 100644 --- a/app/dockview.cpp +++ b/app/dockview.cpp @@ -378,15 +378,86 @@ void DockView::showConfigurationInterface(Plasma::Applet *applet) } } +//! this is used mainly from vertical panels in order to +//! to get the maximum geometry that can be used from the dock +//! based on their alignment type and the location dock +QRect DockView::maximumNormalGeometry() +{ + if (!this->screen()) { + return; + } + + int xPos = 0; + int yPos = 0; + int maxHeight = maxLength() * screen()->geometry().height(); + int maxWidth = normalThickness(); + + QRect maxGeometry; + + maxGeometry.setRect(0, 0, maxWidth, maxHeight); + + switch (location()) { + case Plasma::Types::LeftEdge: + xPos = screen()->geometry().x(); + + switch (alignment()) { + case Latte::Dock::Top: + yPos = screen()->geometry().y(); + break; + + case Latte::Dock::Center: + case Latte::Dock::Justify: + yPos = qMax(screen()->geometry().center().y() - maxHeight / 2, screen()->geometry().y()); + break; + + case Latte::Dock::Bottom: + yPos = screen()->geometry().bottom() - maxHeight + 1; + break; + } + + maxGeometry.setRect(xPos, yPos, maxWidth, maxHeight); + + break; + + case Plasma::Types::RightEdge: + xPos = screen()->geometry().right() - maxWidth + 1; + + switch (alignment()) { + case Latte::Dock::Top: + yPos = screen()->geometry().y(); + break; + + case Latte::Dock::Center: + case Latte::Dock::Justify: + yPos = qMax(screen()->geometry().center().y() - maxHeight / 2, screen()->geometry().y()); + break; + + case Latte::Dock::Bottom: + yPos = screen()->geometry().bottom() - maxHeight + 1; + break; + } + + maxGeometry.setRect(xPos, yPos, maxWidth, maxHeight); + + break; + } + + return maxGeometry; +} + void DockView::resizeWindow() { if (formFactor() == Plasma::Types::Vertical) { - QSize screenSize = corona()->availableScreenRect(this->containment()->screen()).size(); - QSize size{maxThickness(), screenSize.height()}; + QRegion freeRegion = corona()->availableScreenRegion(this->containment()->screen()); + QRect maximumRect = maximumNormalGeometry(); + QRect availableRect = freeRegion.intersected(maximumRect).boundingRect(); + + //qDebug() << "MAXIMUM RECT :: " << maximumRect << " - AVAILABLE RECT :: " << availableRect; + QSize size{maxThickness(), availableRect.height()}; if (m_drawShadows) { size.setWidth(normalThickness()); - size.setHeight(static_cast(maxLength() * screenSize.height())); + size.setHeight(static_cast(maxLength() * availableRect.height())); } setMinimumSize(size); @@ -432,6 +503,10 @@ void DockView::updatePosition() { QRect screenGeometry; QPoint position; + QRegion freeRegion; + QRect maximumRect; + QRect availableRect; + position = {0, 0}; const auto length = [&](int length) -> int { @@ -466,25 +541,31 @@ void DockView::updatePosition() break; case Plasma::Types::RightEdge: - screenGeometry = corona()->availableScreenRect(this->containment()->screen()); + //screenGeometry = corona()->availableScreenRect(this->containment()->screen()); + freeRegion = corona()->availableScreenRegion(this->containment()->screen()); + maximumRect = maximumNormalGeometry(); + availableRect = freeRegion.intersected(maximumRect).boundingRect(); if (m_drawShadows && !mask().isNull()) { - position = {screenGeometry.x() + screenGeometry.width() - cleanThickness, - screenGeometry.y() + length(screenGeometry.height()) + position = {availableRect.right() - cleanThickness + 1, + availableRect.y() + length(availableRect.height()) }; } else { - position = {screenGeometry.x() + screenGeometry.width() - width(), screenGeometry.y()}; + position = {availableRect.right() - width() + 1, availableRect.y()}; } break; case Plasma::Types::LeftEdge: - screenGeometry = corona()->availableScreenRect(this->containment()->screen()); + //screenGeometry = corona()->availableScreenRect(this->containment()->screen()); + freeRegion = corona()->availableScreenRegion(this->containment()->screen()); + maximumRect = maximumNormalGeometry(); + availableRect = freeRegion.intersected(maximumRect).boundingRect(); if (m_drawShadows && !mask().isNull()) { - position = {screenGeometry.x(), screenGeometry.y() + length(screenGeometry.height())}; + position = {availableRect.x(), availableRect.y() + length(availableRect.height())}; } else { - position = {screenGeometry.x(), screenGeometry.y()}; + position = {availableRect.x(), availableRect.y()}; } break; diff --git a/app/dockview.h b/app/dockview.h index 930263f7c..d5f9425d0 100644 --- a/app/dockview.h +++ b/app/dockview.h @@ -184,6 +184,8 @@ private: void updatePosition(); void updateFormFactor(); + QRect maximumNormalGeometry(); + private: Plasma::Containment *containmentById(uint id);