Introduce Platform::outputAt()

With AbstractOutput being used more heavily, it makes sense to have
something like Screens::number() in the Platform class. As is, the steps
to get an output for a given point are awkward - first, get the screen
id, then use the screen id to get the output.
This commit is contained in:
Vlad Zahorodnii 2021-08-27 18:49:54 +03:00
parent 1dc749333e
commit d228829abb
7 changed files with 37 additions and 31 deletions

View file

@ -1327,11 +1327,11 @@ void AbstractClient::handleInteractiveMoveResize(int x, int y, int x_root, int y
Q_ASSERT(mode == PositionCenter);
if (!isMovable()) { // isMovableAcrossScreens() must have been true to get here
// Special moving of maximized windows on Xinerama screens
int screen = screens()->number(globalPos);
AbstractOutput *output = kwinApp()->platform()->outputAt(globalPos);
if (isFullScreen())
setMoveResizeGeometry(workspace()->clientArea(FullScreenArea, this, screen));
setMoveResizeGeometry(workspace()->clientArea(FullScreenArea, this, output));
else {
QRect moveResizeGeom = workspace()->clientArea(MaximizeArea, this, screen);
QRect moveResizeGeom = workspace()->clientArea(MaximizeArea, this, output);
QSize adjSize = constrainFrameSize(moveResizeGeom.size(), SizeModeMax);
if (adjSize != moveResizeGeom.size()) {
QRect r(moveResizeGeom);
@ -3382,8 +3382,7 @@ void AbstractClient::checkWorkspacePosition(QRect oldGeometry, QRect oldClientGe
}
}
} else {
const int oldScreen = screens()->number(oldGeometry.center());
oldScreenArea = workspace()->clientArea(ScreenArea, kwinApp()->platform()->findOutput(oldScreen), oldDesktop);
oldScreenArea = workspace()->clientArea(ScreenArea, kwinApp()->platform()->outputAt(oldGeometry.center()), oldDesktop);
}
const QRect oldGeomTall = QRect(oldGeometry.x(), oldScreenArea.y(), oldGeometry.width(), oldScreenArea.height()); // Full screen height
const QRect oldGeomWide = QRect(oldScreenArea.x(), oldGeometry.y(), oldScreenArea.width(), oldGeometry.height()); // Full screen width

View file

@ -170,6 +170,28 @@ AbstractOutput *Platform::findOutput(const QUuid &uuid) const
return nullptr;
}
AbstractOutput *Platform::outputAt(const QPoint &pos) const
{
AbstractOutput *bestOutput = nullptr;
int minDistance = INT_MAX;
const auto candidates = enabledOutputs();
for (AbstractOutput *output : candidates) {
const QRect &geo = output->geometry();
if (geo.contains(pos)) {
return output;
}
int distance = QPoint(geo.topLeft() - pos).manhattanLength();
distance = std::min(distance, QPoint(geo.topRight() - pos).manhattanLength());
distance = std::min(distance, QPoint(geo.bottomRight() - pos).manhattanLength());
distance = std::min(distance, QPoint(geo.bottomLeft() - pos).manhattanLength());
if (distance < minDistance) {
minDistance = distance;
bestOutput = output;
}
}
return bestOutput;
}
bool Platform::usesSoftwareCursor() const
{
return m_softwareCursor;

View file

@ -352,6 +352,7 @@ public:
}
AbstractOutput *findOutput(int screenId) const;
AbstractOutput *findOutput(const QUuid &uuid) const;
AbstractOutput *outputAt(const QPoint &pos) const;
/**
* A string of information to include in kwin debug output

View file

@ -9,6 +9,7 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "pointer_input.h"
#include "abstract_output.h"
#include "platform.h"
#include "x11client.h"
#include "effects.h"
@ -813,8 +814,8 @@ void PointerInputRedirection::updatePosition(const QPointF &pos)
const QRectF unitedScreensGeometry = screens()->geometry();
p = confineToBoundingBox(p, unitedScreensGeometry);
if (!screenContainsPos(p)) {
const QRectF currentScreenGeometry = screens()->geometry(screens()->number(m_pos.toPoint()));
p = confineToBoundingBox(p, currentScreenGeometry);
const AbstractOutput *currentOutput = kwinApp()->platform()->outputAt(m_pos.toPoint());
p = confineToBoundingBox(p, currentOutput->geometry());
}
}
p = applyPointerConfinement(p);
@ -903,9 +904,9 @@ void PointerInputRedirection::updateAfterScreenChange()
return;
}
// pointer no longer on a screen, reposition to closes screen
const QPointF pos = screens()->geometry(screens()->number(m_pos.toPoint())).center();
const AbstractOutput *output = kwinApp()->platform()->outputAt(m_pos.toPoint());
// TODO: better way to get timestamps
processMotion(pos, waylandServer()->seat()->timestamp());
processMotion(output->geometry().center(), waylandServer()->seat()->timestamp());
}
QPointF PointerInputRedirection::position() const

View file

@ -295,24 +295,7 @@ int Screens::number(const QPoint &pos) const
Q_UNUSED(pos)
return -1;
#else
int bestScreen = 0;
int minDistance = INT_MAX;
const auto outputs = kwinApp()->platform()->enabledOutputs();
for (int i = 0; i < outputs.size(); ++i) {
const QRect &geo = outputs[i]->geometry();
if (geo.contains(pos)) {
return i;
}
int distance = QPoint(geo.topLeft() - pos).manhattanLength();
distance = qMin(distance, QPoint(geo.topRight() - pos).manhattanLength());
distance = qMin(distance, QPoint(geo.bottomRight() - pos).manhattanLength());
distance = qMin(distance, QPoint(geo.bottomLeft() - pos).manhattanLength());
if (distance < minDistance) {
minDistance = distance;
bestScreen = i;
}
}
return bestScreen;
return kwinApp()->platform()->enabledOutputs().indexOf(kwinApp()->platform()->outputAt(pos));
#endif
}

View file

@ -2433,9 +2433,9 @@ QPoint Workspace::adjustClientPosition(AbstractClient* c, QPoint pos, bool unres
if (options->windowSnapZone() || !borderSnapZone.isNull() || options->centerSnapZone()) {
const bool sOWO = options->isSnapOnlyWhenOverlapping();
const int screen = screens()->number(pos + c->rect().center());
const AbstractOutput *output = kwinApp()->platform()->outputAt(pos + c->rect().center());
if (maxRect.isNull())
maxRect = clientArea(MovementArea, c, screen);
maxRect = clientArea(MovementArea, c, output);
const int xmin = maxRect.left();
const int xmax = maxRect.right() + 1; //desk size
const int ymin = maxRect.top();

View file

@ -1565,8 +1565,8 @@ void XdgToplevelClient::setFullScreen(bool set, bool user)
updateDecoration(false, false);
if (set) {
const int screen = m_fullScreenRequestedOutput ? kwinApp()->platform()->enabledOutputs().indexOf(m_fullScreenRequestedOutput) : screens()->number(moveResizeGeometry().center());
moveResize(workspace()->clientArea(FullScreenArea, this, screen));
const AbstractOutput *output = m_fullScreenRequestedOutput ? m_fullScreenRequestedOutput.data() : kwinApp()->platform()->outputAt(moveResizeGeometry().center());
moveResize(workspace()->clientArea(FullScreenArea, this, output));
} else {
m_fullScreenRequestedOutput.clear();
if (fullscreenGeometryRestore().isValid()) {