Libplasma

windowresizehandler.cpp
1/*
2 SPDX-FileCopyrightText: 2023 David Edmundson <davidedmundson@kde.org>
3 SPDX-FileCopyrightText: 2022 Luca Carlon<carlon.luca@gmail.com>
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "windowresizehandler.h"
8
9#include <QEvent>
10#include <QMouseEvent>
11#include <QWindow>
12
13using namespace PlasmaQuick;
14
15class WindowResizeHandlerPrivate
16{
17public:
18 QWindow *window;
19 QMargins margins;
20 Qt::Edges activeEdges;
21
22 bool updateMouseCursor(const QPointF &globalMousePos);
23 void unsetMouseCursor();
24
25 Qt::Edges hitTest(const QPointF &pos);
26
27private:
28 bool overridingCursor = false;
29 bool hitTestLeft(const QPointF &pos);
30 bool hitTestRight(const QPointF &pos);
31 bool hitTestTop(const QPointF &pos);
32 bool hitTestBottom(const QPointF &pos);
33};
34
35PlasmaQuick::WindowResizeHandler::WindowResizeHandler(QWindow *parent)
36 : QObject(parent)
37 , d(new WindowResizeHandlerPrivate)
38{
39 d->window = parent;
40 d->window->installEventFilter(this);
41}
42
43WindowResizeHandler::~WindowResizeHandler()
44{
45 d->window->removeEventFilter(this);
46}
47
48void WindowResizeHandler::setMargins(const QMargins &margins)
49{
50 d->margins = margins;
51}
52
53QMargins WindowResizeHandler::margins() const
54{
55 return d->margins;
56}
57
58void WindowResizeHandler::setActiveEdges(Qt::Edges edges)
59{
60 d->activeEdges = edges;
61}
62
63Qt::Edges WindowResizeHandler::activeEdges() const
64{
65 return d->activeEdges;
66}
67
68bool WindowResizeHandler::eventFilter(QObject *watched, QEvent *event)
69{
70 Q_UNUSED(watched)
71 switch (event->type()) {
72 case QEvent::Enter: {
73 QEnterEvent *ee = static_cast<QEnterEvent *>(event);
74 d->updateMouseCursor(ee->globalPosition());
75 return false;
76 }
77 case QEvent::Leave:
78 d->unsetMouseCursor();
79 return false;
83 QMouseEvent *me = static_cast<QMouseEvent *>(event);
84 if (event->type() == QEvent::MouseMove && d->updateMouseCursor(me->globalPosition())) {
85 return false;
86 }
87 if (event->type() == QEvent::MouseButtonPress) {
88 const QPointF globalMousePos = me->globalPosition();
89 const Qt::Edges sides = d->hitTest(globalMousePos) & d->activeEdges;
90 if (sides) {
91 d->window->startSystemResize(sides);
92 return true;
93 }
94 }
95 } break;
96 default:
97 break;
98 }
99 return false;
100}
101
102bool WindowResizeHandlerPrivate::updateMouseCursor(const QPointF &globalMousePos)
103{
104 Qt::Edges sides = hitTest(globalMousePos) & activeEdges;
105 if (!sides) {
106 unsetMouseCursor();
107 return false;
108 }
109
110 if (sides == Qt::Edges(Qt::LeftEdge | Qt::TopEdge)) {
112 } else if (sides == Qt::Edges(Qt::RightEdge | Qt::TopEdge)) {
114 } else if (sides == Qt::Edges(Qt::LeftEdge | Qt::BottomEdge)) {
116 } else if (sides == Qt::Edges(Qt::RightEdge | Qt::BottomEdge)) {
118 } else if (sides.testFlag(Qt::TopEdge)) {
120 } else if (sides.testFlag(Qt::LeftEdge)) {
122 } else if (sides.testFlag(Qt::RightEdge)) {
124 } else {
126 }
127
128 overridingCursor = true;
129 return true;
130}
131
132void WindowResizeHandlerPrivate::unsetMouseCursor()
133{
134 if (overridingCursor) {
136 overridingCursor = false;
137 }
138}
139
140Qt::Edges WindowResizeHandlerPrivate::hitTest(const QPointF &pos)
141{
142 bool left = hitTestLeft(pos);
143 bool right = hitTestRight(pos);
144 bool top = hitTestTop(pos);
145 bool bottom = hitTestBottom(pos);
146 Qt::Edges edges;
147 if (left) {
148 edges.setFlag(Qt::LeftEdge);
149 }
150 if (right) {
151 edges.setFlag(Qt::RightEdge);
152 }
153 if (bottom) {
154 edges.setFlag(Qt::BottomEdge);
155 }
156 if (top) {
157 edges.setFlag(Qt::TopEdge);
158 }
159
160 return edges;
161}
162
163bool WindowResizeHandlerPrivate::hitTestLeft(const QPointF &pos)
164{
165 const QRect geometry = window->geometry();
166 const QRectF rect(geometry.x(), geometry.y(), margins.left(), geometry.height());
167 return rect.contains(pos);
168}
169
170bool WindowResizeHandlerPrivate::hitTestRight(const QPointF &pos)
171{
172 const QRect geometry = window->geometry();
173 const QRectF rect(geometry.x() + geometry.width() - margins.right(), geometry.y(), margins.right(), geometry.height());
174 return rect.contains(pos);
175}
176
177bool WindowResizeHandlerPrivate::hitTestTop(const QPointF &pos)
178{
179 const QRect geometry = window->geometry();
180 const QRectF rect(geometry.x(), geometry.y(), geometry.width(), margins.top());
181 return rect.contains(pos);
182}
183
184bool WindowResizeHandlerPrivate::hitTestBottom(const QPointF &pos)
185{
186 const QRect geometry = window->geometry();
187 const QRectF rect(geometry.x(), geometry.y() + geometry.height() - margins.bottom(), geometry.width(), margins.bottom());
188 return rect.contains(pos);
189}
QWidget * window(QObject *job)
The EdgeEventForwarder class This class forwards edge events to be replayed within the given margin T...
Definition action.h:20
virtual bool event(QEvent *e)
void installEventFilter(QObject *filterObj)
int height() const const
int width() const const
int x() const const
int y() const const
QPointF globalPosition() const const
SizeFDiagCursor
typedef Edges
QTextStream & left(QTextStream &stream)
QTextStream & right(QTextStream &stream)
void setCursor(const QCursor &)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:34:35 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.