Floor coordinates to check if a point is inside a region

More correct since QRegion models half open intervals (like QRect) and toPoint
rounds the coordinates. Fixes an issue where one could escape a pointer
confinement by just moving the mouse.
This commit is contained in:
David Redondo 2022-08-18 10:05:00 +02:00
parent 6bf53c8797
commit e5aeb674c0
3 changed files with 14 additions and 5 deletions

View file

@ -70,6 +70,8 @@
#include <xkbcommon/xkbcommon.h>
#include <cmath>
namespace KWin
{
@ -3440,7 +3442,7 @@ void InputDeviceHandler::updateDecoration()
Decoration::DecoratedClientImpl *decoration = nullptr;
auto hover = m_hover.window.data();
if (hover && hover->decoratedClient()) {
if (!hover->clientGeometry().toRect().contains(position().toPoint())) {
if (!hover->clientGeometry().toRect().contains(QPoint(std::floor(position().x()), std::floor(position().y())))) {
// input device above decoration
decoration = hover->decoratedClient();
}

View file

@ -45,6 +45,8 @@
#include <linux/input.h>
#include <cmath>
namespace KWin
{
@ -770,18 +772,23 @@ QPointF PointerInputRedirection::applyPointerConfinement(const QPointF &pos) con
return pos;
}
auto floorPoint = [](const QPointF &point) {
return QPoint(std::floor(point.x()), std::floor(point.y()));
};
const QRegion confinementRegion = getConstraintRegion(focus(), cf);
if (confinementRegion.contains(pos.toPoint())) {
if (confinementRegion.contains(floorPoint(pos))) {
return pos;
}
QPointF p = pos;
// allow either x or y to pass
p = QPointF(m_pos.x(), pos.y());
if (confinementRegion.contains(p.toPoint())) {
if (confinementRegion.contains(floorPoint(p))) {
return p;
}
p = QPointF(pos.x(), m_pos.y());
if (confinementRegion.contains(p.toPoint())) {
if (confinementRegion.contains(floorPoint(p))) {
return p;
}

View file

@ -772,7 +772,7 @@ bool SurfaceInterfacePrivate::contains(const QPointF &position) const
bool SurfaceInterfacePrivate::inputContains(const QPointF &position) const
{
return contains(position) && inputRegion.contains(position.toPoint());
return contains(position) && inputRegion.contains(QPoint(std::floor(position.x()), std::floor(position.y())));
}
QRegion SurfaceInterface::damage() const