ScreenEdgeInputFilter for checking whether a screenedge gets activated

So far the area based edges connected directly to global pointer pos
changed in InputRedirection. This didn't allow proper checking whether
the edge was triggered (e.g. missing timestamp).

This change merges the functionality into the new input filter mechanism.
There is now a dedicated input filter for screen edges, installed after
lock screen and before effects. It always passes events on, but also passes
all events through ScreenEdges to handle the activation. As it's installed
after the lock screen filter we don't need to check for screen locked any
more.

The code is now similar strucutured to the existing X11 based variants
and maybe will allow to also merge the X11 variant with the new one.
icc-effect-5.14.5
Martin Gräßlin 2016-02-11 15:51:25 +01:00
parent a51171720e
commit 9b917a20fe
3 changed files with 59 additions and 38 deletions

View File

@ -27,6 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "tabbox/tabbox.h"
#endif
#include "unmanaged.h"
#include "screenedge.h"
#include "screens.h"
#include "workspace.h"
#if HAVE_INPUT
@ -686,6 +687,17 @@ public:
};
#endif
class ScreenEdgeInputFilter : public InputEventFilter
{
public:
bool pointerEvent(QMouseEvent *event, quint32 nativeButton) override {
Q_UNUSED(nativeButton)
ScreenEdges::self()->isEntered(event);
// always forward
return false;
}
};
/**
* The remaining default input filter which forwards events to other windows
**/
@ -940,6 +952,7 @@ void InputRedirection::setupInputFilters()
if (waylandServer()) {
installInputEventFilter(new LockScreenFilter);
}
installInputEventFilter(new ScreenEdgeInputFilter);
installInputEventFilter(new EffectsFilter);
installInputEventFilter(new MoveResizeFilter);
installInputEventFilter(new GlobalShortcutFilter);

View File

@ -33,20 +33,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "atoms.h"
#include <client.h>
#include "cursor.h"
#include "input.h"
#include "main.h"
#include "screens.h"
#include "utils.h"
#include <workspace.h>
#include "virtualdesktops.h"
#ifndef KWIN_UNIT_TEST
#include "wayland_server.h"
#endif
// DBus generated
#include "screenlocker_interface.h"
// frameworks
#include <KConfigGroup>
// Qt
#include <QMouseEvent>
#include <QSharedPointer>
#include <QTimer>
#include <QVector>
@ -593,42 +590,12 @@ void WindowBasedEdge::doUpdateBlocking()
AreaBasedEdge::AreaBasedEdge(ScreenEdges* parent)
: Edge(parent)
{
connect(input(), SIGNAL(globalPointerChanged(QPointF)), SLOT(pointerPosChanged(QPointF)));
}
AreaBasedEdge::~AreaBasedEdge()
{
}
void AreaBasedEdge::pointerPosChanged(const QPointF &pos)
{
#ifndef KWIN_UNIT_TEST
if (waylandServer() && waylandServer()->isScreenLocked()) {
return;
}
#endif
if (!isReserved()) {
return;
}
const QPoint p = pos.toPoint();
if (approachGeometry().contains(p)) {
if (!isApproaching()) {
startApproaching();
} else {
updateApproaching(p);
}
} else {
if (isApproaching()) {
stopApproaching();
}
}
if (geometry().contains(p)) {
// we don't push the cursor back as pointer warping is not supported on Wayland
// TODO: this clearly needs improving
check(p, QDateTime(), true);
}
}
/**********************************************************
* ScreenEdges
*********************************************************/
@ -1231,6 +1198,47 @@ bool ScreenEdges::isEntered(xcb_client_message_event_t *event)
QPoint(event->data.data32[2] >> 16, event->data.data32[2] & 0xffff));
}
bool ScreenEdges::isEntered(QMouseEvent *event)
{
if (event->type() != QEvent::MouseMove) {
return false;
}
bool activated = false;
bool activatedForClient = false;
for (auto it = m_edges.begin(); it != m_edges.end(); ++it) {
Edge *edge = *it;
if (!edge->isReserved()) {
continue;
}
if (edge->approachGeometry().contains(event->globalPos())) {
if (!edge->isApproaching()) {
edge->startApproaching();
} else {
edge->updateApproaching(event->globalPos());
}
} else {
if (edge->isApproaching()) {
edge->stopApproaching();
}
}
if (edge->geometry().contains(event->globalPos())) {
if (edge->check(event->globalPos(), QDateTime::fromMSecsSinceEpoch(event->timestamp()))) {
if (edge->client()) {
activatedForClient = true;
}
}
}
}
if (activatedForClient) {
for (auto it = m_edges.constBegin(); it != m_edges.constEnd(); ++it) {
if ((*it)->client()) {
(*it)->markAsTriggered(event->globalPos(), QDateTime::fromMSecsSinceEpoch(event->timestamp()));
}
}
}
return activated;
}
bool ScreenEdges::handleEnterNotifiy(xcb_window_t window, const QPoint &point, const QDateTime &timestamp)
{
bool activated = false;

View File

@ -39,6 +39,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QVector>
#include <QDateTime>
class QMouseEvent;
namespace KWin {
class Client;
@ -70,6 +72,7 @@ public:
bool isApproaching() const;
void setClient(Client *client);
Client *client() const;
const QRect &geometry() const;
public Q_SLOTS:
void reserve();
@ -85,7 +88,6 @@ Q_SIGNALS:
protected:
ScreenEdges *edges();
const ScreenEdges *edges() const;
const QRect &geometry() const;
bool isBlocked() const;
virtual void doGeometryUpdate();
virtual void activate();
@ -152,9 +154,6 @@ class AreaBasedEdge : public Edge
public:
explicit AreaBasedEdge(ScreenEdges *parent);
virtual ~AreaBasedEdge();
private Q_SLOTS:
void pointerPosChanged(const QPointF &pos);
};
/**
@ -301,6 +300,7 @@ public:
bool isEntered(xcb_generic_event_t *e);
bool isEntered(xcb_enter_notify_event_t *e);
bool isEntered(xcb_client_message_event_t *e);
bool isEntered(QMouseEvent *event);
/**
* Returns a QVector of all existing screen edge windows