Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qwidgetresizehandler.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include "qframe.h"
7#include "qapplication.h"
8#include "private/qwidget_p.h"
9#include "qcursor.h"
10#if QT_CONFIG(sizegrip)
11#include "qsizegrip.h"
12#endif
13#include "qevent.h"
14#include "qdebug.h"
15#include "private/qlayoutengine_p.h"
16
18
19using namespace Qt::StringLiterals;
20
21#define RANGE 4
22
24static bool resizeVerticalDirectionFixed = false;
25
27 : QObject(parent), widget(parent), childWidget(cw ? cw : parent),
28 fw(0), extrahei(0), buttonDown(false), active(false)
29{
30 mode = Nowhere;
31 widget->setMouseTracking(true);
32 QFrame *frame = qobject_cast<QFrame*>(widget);
35 enabled = true;
36 widget->installEventFilter(this);
37}
38
40{
41 if (b == enabled)
42 return;
43
44 enabled = b;
45 if (!enabled)
46 setMouseCursor(Nowhere);
47}
48
50{
51 return enabled;
52}
53
55{
56 if (!isEnabled()
59 && ee->type() != QEvent::MouseMove
60 && ee->type() != QEvent::KeyPress
62 )
63 return false;
64
65 Q_ASSERT(o == widget);
66 QWidget *w = widget;
68 if (buttonDown && ee->type() == QEvent::MouseButtonRelease)
69 buttonDown = false;
70 return false;
71 }
72
73 switch (ee->type()) {
75 QMouseEvent *e = static_cast<QMouseEvent *>(ee);
76 if (w->isMaximized())
77 break;
78 const QRect widgetRect = widget->rect().marginsAdded(QMargins(range, range, range, range));
79 const QPoint cursorPoint = widget->mapFromGlobal(e->globalPosition().toPoint());
80 if (!widgetRect.contains(cursorPoint))
81 return false;
82 if (e->button() == Qt::LeftButton) {
83 buttonDown = false;
84 emit activate();
86 buttonDown = true;
87 moveOffset = widget->mapFromGlobal(e->globalPosition().toPoint());
88 invertedMoveOffset = widget->rect().bottomRight() - moveOffset;
89 if (mode != Center)
90 return true;
91 }
92 } break;
94 if (w->isMaximized())
95 break;
96 if (static_cast<QMouseEvent *>(ee)->button() == Qt::LeftButton) {
97 active = false;
98 buttonDown = false;
99 widget->releaseMouse();
100 widget->releaseKeyboard();
101 if (mode != Center)
102 return true;
103 }
104 break;
105 case QEvent::MouseMove: {
106 if (w->isMaximized())
107 break;
108 QMouseEvent *e = static_cast<QMouseEvent *>(ee);
109 buttonDown = buttonDown && (e->buttons() & Qt::LeftButton); // safety, state machine broken!
111 if (mode != Center)
112 return true;
113 } break;
114 case QEvent::KeyPress:
115 keyPressEvent(static_cast<QKeyEvent *>(ee));
116 break;
119 if (buttonDown) {
120 ee->accept();
121 return true;
122 }
123 break;
124 default:
125 break;
126 }
127
128 return false;
129}
130
132{
134 if (!active && !buttonDown) {
135 if (pos.y() <= range && pos.x() <= range)
136 mode = TopLeft;
137 else if (pos.y() >= widget->height()-range && pos.x() >= widget->width()-range)
138 mode = BottomRight;
139 else if (pos.y() >= widget->height()-range && pos.x() <= range)
140 mode = BottomLeft;
141 else if (pos.y() <= range && pos.x() >= widget->width()-range)
142 mode = TopRight;
143 else if (pos.y() <= range)
144 mode = Top;
145 else if (pos.y() >= widget->height()-range)
146 mode = Bottom;
147 else if (pos.x() <= range)
148 mode = Left;
149 else if ( pos.x() >= widget->width()-range)
150 mode = Right;
151 else if (widget->rect().contains(pos))
152 mode = Center;
153 else
154 mode = Nowhere;
155
156 if (widget->isMinimized() || !isEnabled())
157 mode = Center;
158#ifndef QT_NO_CURSOR
159 setMouseCursor(mode);
160#endif
161 return;
162 }
163
164 if (mode == Center)
165 return;
166
168 return;
169
170
171 QPoint globalPos = (!widget->isWindow() && widget->parentWidget()) ?
173 if (!widget->isWindow() && !widget->parentWidget()->rect().contains(globalPos)) {
174 if (globalPos.x() < 0)
175 globalPos.rx() = 0;
176 if (globalPos.y() < 0)
177 globalPos.ry() = 0;
178 if (globalPos.x() > widget->parentWidget()->width())
179 globalPos.rx() = widget->parentWidget()->width();
180 if (globalPos.y() > widget->parentWidget()->height())
181 globalPos.ry() = widget->parentWidget()->height();
182 }
183
184 QPoint p = globalPos + invertedMoveOffset;
185 QPoint pp = globalPos - moveOffset;
186
187 // Workaround for window managers which refuse to move a tool window partially offscreen.
188 if (QGuiApplication::platformName() == "xcb"_L1) {
189 const QRect desktop = QWidgetPrivate::availableScreenGeometry(widget);
190 pp.rx() = qMax(pp.x(), desktop.left());
191 pp.ry() = qMax(pp.y(), desktop.top());
192 p.rx() = qMin(p.x(), desktop.right());
193 p.ry() = qMin(p.y(), desktop.bottom());
194 }
195
196 QSize ms = qSmartMinSize(childWidget);
197 int mw = ms.width();
198 int mh = ms.height();
199 if (childWidget != widget) {
200 mw += 2 * fw;
201 mh += 2 * fw + extrahei;
202 }
203
204 QSize maxsize(childWidget->maximumSize());
205 if (childWidget != widget)
206 maxsize += QSize(2 * fw, 2 * fw + extrahei);
207 QSize mpsize(widget->geometry().right() - pp.x() + 1,
208 widget->geometry().bottom() - pp.y() + 1);
209 mpsize = mpsize.expandedTo(widget->minimumSize()).expandedTo(QSize(mw, mh))
210 .boundedTo(maxsize);
211 QPoint mp(widget->geometry().right() - mpsize.width() + 1,
212 widget->geometry().bottom() - mpsize.height() + 1);
213
214 QRect geom = widget->geometry();
215
216 switch (mode) {
217 case TopLeft:
218 geom = QRect(mp, widget->geometry().bottomRight()) ;
219 break;
220 case BottomRight:
221 geom = QRect(widget->geometry().topLeft(), p) ;
222 break;
223 case BottomLeft:
224 geom = QRect(QPoint(mp.x(), widget->geometry().y()), QPoint(widget->geometry().right(), p.y())) ;
225 break;
226 case TopRight:
227 geom = QRect(QPoint(widget->geometry().x(), mp.y()), QPoint(p.x(), widget->geometry().bottom())) ;
228 break;
229 case Top:
230 geom = QRect(QPoint(widget->geometry().left(), mp.y()), widget->geometry().bottomRight()) ;
231 break;
232 case Bottom:
233 geom = QRect(widget->geometry().topLeft(), QPoint(widget->geometry().right(), p.y())) ;
234 break;
235 case Left:
236 geom = QRect(QPoint(mp.x(), widget->geometry().top()), widget->geometry().bottomRight()) ;
237 break;
238 case Right:
239 geom = QRect(widget->geometry().topLeft(), QPoint(p.x(), widget->geometry().bottom())) ;
240 break;
241 default:
242 break;
243 }
244
245 geom = QRect(geom.topLeft(),
246 geom.size().expandedTo(widget->minimumSize())
247 .expandedTo(QSize(mw, mh))
248 .boundedTo(maxsize));
249
250 if (geom != widget->geometry() &&
251 (widget->isWindow() || widget->parentWidget()->rect().intersects(geom))) {
252 widget->setGeometry(geom);
253 }
254}
255
256void QWidgetResizeHandler::setMouseCursor(MousePosition m)
257{
258#ifdef QT_NO_CURSOR
259 Q_UNUSED(m);
260#else
261 QObjectList children = widget->children();
262 for (int i = 0; i < children.size(); ++i) {
263 if (QWidget *w = qobject_cast<QWidget*>(children.at(i))) {
264 if (!w->testAttribute(Qt::WA_SetCursor)) {
265 w->setCursor(Qt::ArrowCursor);
266 }
267 }
268 }
269
270 switch (m) {
271 case TopLeft:
272 case BottomRight:
274 break;
275 case BottomLeft:
276 case TopRight:
278 break;
279 case Top:
280 case Bottom:
282 break;
283 case Left:
284 case Right:
286 break;
287 default:
288 widget->setCursor(Qt::ArrowCursor);
289 break;
290 }
291#endif // QT_NO_CURSOR
292}
293
295{
296 if (!isResizing())
297 return;
298 bool is_control = e->modifiers() & Qt::ControlModifier;
299 int delta = is_control?1:8;
301 switch (e->key()) {
302 case Qt::Key_Left:
303 pos.rx() -= delta;
305 if (mode == TopLeft || mode == BottomLeft) {
306 moveOffset.rx() += delta;
307 invertedMoveOffset.rx() += delta;
308 } else {
309 moveOffset.rx() -= delta;
310 invertedMoveOffset.rx() -= delta;
311 }
312 }
313 if (isResizing() && !resizeHorizontalDirectionFixed) {
315 if (mode == BottomRight)
316 mode = BottomLeft;
317 else if (mode == TopRight)
318 mode = TopLeft;
319#ifndef QT_NO_CURSOR
320 setMouseCursor(mode);
321 widget->grabMouse(widget->cursor());
322#else
323 widget->grabMouse();
324#endif
325 }
326 break;
327 case Qt::Key_Right:
328 pos.rx() += delta;
330 if (mode == TopRight || mode == BottomRight) {
331 moveOffset.rx() += delta;
332 invertedMoveOffset.rx() += delta;
333 } else {
334 moveOffset.rx() -= delta;
335 invertedMoveOffset.rx() -= delta;
336 }
337 }
338 if (isResizing() && !resizeHorizontalDirectionFixed) {
340 if (mode == BottomLeft)
341 mode = BottomRight;
342 else if (mode == TopLeft)
343 mode = TopRight;
344#ifndef QT_NO_CURSOR
345 setMouseCursor(mode);
346 widget->grabMouse(widget->cursor());
347#else
348 widget->grabMouse();
349#endif
350 }
351 break;
352 case Qt::Key_Up:
353 pos.ry() -= delta;
355 if (mode == TopLeft || mode == TopRight) {
356 moveOffset.ry() += delta;
357 invertedMoveOffset.ry() += delta;
358 } else {
359 moveOffset.ry() -= delta;
360 invertedMoveOffset.ry() -= delta;
361 }
362 }
363 if (isResizing() && !resizeVerticalDirectionFixed) {
365 if (mode == BottomLeft)
366 mode = TopLeft;
367 else if (mode == BottomRight)
368 mode = TopRight;
369#ifndef QT_NO_CURSOR
370 setMouseCursor(mode);
371 widget->grabMouse(widget->cursor());
372#else
373 widget->grabMouse();
374#endif
375 }
376 break;
377 case Qt::Key_Down:
378 pos.ry() += delta;
380 if (mode == BottomLeft || mode == BottomRight) {
381 moveOffset.ry() += delta;
382 invertedMoveOffset.ry() += delta;
383 } else {
384 moveOffset.ry() -= delta;
385 invertedMoveOffset.ry() -= delta;
386 }
387 }
388 if (isResizing() && !resizeVerticalDirectionFixed) {
390 if (mode == TopLeft)
391 mode = BottomLeft;
392 else if (mode == TopRight)
393 mode = BottomRight;
394#ifndef QT_NO_CURSOR
395 setMouseCursor(mode);
396 widget->grabMouse(widget->cursor());
397#else
398 widget->grabMouse();
399#endif
400 }
401 break;
402 case Qt::Key_Space:
403 case Qt::Key_Return:
404 case Qt::Key_Enter:
405 case Qt::Key_Escape:
406 active = false;
407 widget->releaseMouse();
408 widget->releaseKeyboard();
409 buttonDown = false;
410 break;
411 default:
412 return;
413 }
415}
416
417
419{
420 if (!enabled)
421 return;
422
423 active = true;
424 moveOffset = widget->mapFromGlobal(QCursor::pos());
425 if (moveOffset.x() < widget->width()/2) {
426 if (moveOffset.y() < widget->height()/2)
427 mode = TopLeft;
428 else
429 mode = BottomLeft;
430 } else {
431 if (moveOffset.y() < widget->height()/2)
432 mode = TopRight;
433 else
434 mode = BottomRight;
435 }
436 invertedMoveOffset = widget->rect().bottomRight() - moveOffset;
437#ifndef QT_NO_CURSOR
438 setMouseCursor(mode);
439 widget->grabMouse(widget->cursor() );
440#else
441 widget->grabMouse();
442#endif
443 widget->grabKeyboard();
446}
447
449
450#include "moc_qwidgetresizehandler_p.cpp"
static QWidget * activePopupWidget()
Returns the active popup widget.
static void setPos(int x, int y)
Moves the cursor (hot spot) of the primary screen to the global screen position (x,...
Definition qcursor.cpp:240
static QPoint pos()
Returns the position of the cursor (hot spot) of the primary screen in global screen coordinates.
Definition qcursor.cpp:188
\inmodule QtCore
Definition qcoreevent.h:45
@ ShortcutOverride
Definition qcoreevent.h:158
@ MouseMove
Definition qcoreevent.h:63
@ KeyPress
Definition qcoreevent.h:64
@ MouseButtonPress
Definition qcoreevent.h:60
@ MouseButtonRelease
Definition qcoreevent.h:61
Type type() const
Returns the event type.
Definition qcoreevent.h:304
void accept()
Sets the accept flag of the event object, the equivalent of calling setAccepted(true).
Definition qcoreevent.h:310
The QFrame class is the base class of widgets that can have a frame.
Definition qframe.h:17
int frameWidth
the width of the frame that is drawn.
Definition qframe.h:24
QScreen * primaryScreen
the primary (or default) screen of the application.
QString platformName
The name of the underlying platform plugin.
static Qt::MouseButtons mouseButtons()
Returns the current state of the buttons on the mouse.
The QKeyEvent class describes a key event.
Definition qevent.h:424
Qt::KeyboardModifiers modifiers() const
Returns the keyboard modifier flags that existed immediately after the event occurred.
Definition qevent.cpp:1468
int key() const
Returns the code of the key that was pressed or released.
Definition qevent.h:434
qsizetype size() const noexcept
Definition qlist.h:397
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
\inmodule QtCore
Definition qmargins.h:24
\inmodule QtGui
Definition qevent.h:196
\inmodule QtCore
Definition qobject.h:103
void installEventFilter(QObject *filterObj)
Installs an event filter filterObj on this object.
Definition qobject.cpp:2339
const QObjectList & children() const
Returns a list of child objects.
Definition qobject.h:201
constexpr QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
Definition qpoint.h:404
\inmodule QtCore\reentrant
Definition qpoint.h:25
constexpr int & ry() noexcept
Returns a reference to the y coordinate of this point.
Definition qpoint.h:160
constexpr int & rx() noexcept
Returns a reference to the x coordinate of this point.
Definition qpoint.h:155
constexpr int x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:130
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:135
\inmodule QtCore\reentrant
Definition qrect.h:30
bool intersects(const QRect &r) const noexcept
Returns true if this rectangle intersects with the given rectangle (i.e., there is at least one pixel...
Definition qrect.cpp:1069
constexpr QRect marginsAdded(const QMargins &margins) const noexcept
Returns a rectangle grown by the margins.
Definition qrect.h:448
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:182
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:221
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:176
bool contains(const QRect &r, bool proper=false) const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qrect.cpp:855
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:173
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:185
constexpr QSize size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:242
constexpr QPoint bottomRight() const noexcept
Returns the position of the rectangle's bottom-right corner.
Definition qrect.h:224
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:188
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:179
QRect virtualGeometry
the pixel geometry of the virtual desktop to which this screen belongs
Definition qscreen.h:47
QPointF globalPosition() const
Returns the position of the point in this event on the screen or virtual desktop.
Definition qevent.h:123
Qt::MouseButton button() const
Returns the button that caused the event.
Definition qevent.h:116
Qt::MouseButtons buttons() const
Returns the button state when the event was generated.
Definition qevent.h:117
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
static QRect availableScreenGeometry(const QWidget *widget)
Definition qwidget_p.h:474
bool eventFilter(QObject *o, QEvent *e) override
Filters events if this object has been installed as an event filter for the watched object.
void mouseMoveEvent(QMouseEvent *e)
void keyPressEvent(QKeyEvent *e)
QWidgetResizeHandler(QWidget *parent, QWidget *cw=nullptr)
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
void setGeometry(int x, int y, int w, int h)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qwidget.h:886
void grabKeyboard()
Grabs the keyboard input.
bool isMinimized() const
Definition qwidget.cpp:2836
QSize minimumSize
the widget's minimum size
Definition qwidget.h:120
QRect geometry
the geometry of the widget relative to its parent and excluding the window frame
Definition qwidget.h:106
int width
the width of the widget excluding any window frame
Definition qwidget.h:114
void setMouseTracking(bool enable)
Definition qwidget.h:853
QSize maximumSize
the widget's maximum size in pixels
Definition qwidget.h:121
void releaseKeyboard()
Releases the keyboard grab.
int height
the height of the widget excluding any window frame
Definition qwidget.h:115
QRect rect
the internal geometry of the widget excluding any window frame
Definition qwidget.h:116
QWidget * parentWidget() const
Returns the parent of this widget, or \nullptr if it does not have any parent widget.
Definition qwidget.h:904
void grabMouse()
Grabs the mouse input.
QCursor cursor
the cursor shape for this widget
Definition qwidget.h:135
bool isWindow() const
Returns true if the widget is an independent window, otherwise returns false.
Definition qwidget.h:811
QPointF mapFromGlobal(const QPointF &) const
Translates the global screen coordinate pos to widget coordinates.
void releaseMouse()
Releases the mouse grab.
void setCursor(const QCursor &)
Definition qwidget.cpp:4960
bool testAttribute(Qt::WidgetAttribute) const
Returns true if attribute attribute is set on this widget; otherwise returns false.
Definition qwidget.h:910
QOpenGLWidget * widget
[1]
QPushButton * button
[2]
Combined button and popup list for selecting options.
@ LeftButton
Definition qnamespace.h:58
@ NoButton
Definition qnamespace.h:57
@ WA_SetCursor
Definition qnamespace.h:305
@ WA_WState_ConfigPending
Definition qnamespace.h:331
@ SizeHorCursor
@ SizeVerCursor
@ SizeFDiagCursor
@ ArrowCursor
@ SizeBDiagCursor
@ Key_Escape
Definition qnamespace.h:663
@ Key_Return
Definition qnamespace.h:667
@ Key_Right
Definition qnamespace.h:679
@ Key_Enter
Definition qnamespace.h:668
@ Key_Space
Definition qnamespace.h:513
@ Key_Left
Definition qnamespace.h:677
@ Key_Up
Definition qnamespace.h:678
@ Key_Down
Definition qnamespace.h:680
@ ControlModifier
Q_WIDGETS_EXPORT QSize qSmartMinSize(const QSize &sizeHint, const QSize &minSizeHint, const QSize &minSize, const QSize &maxSize, const QSizePolicy &sizePolicy)
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLboolean GLboolean GLboolean b
GLenum mode
const GLfloat * m
GLfloat GLfloat GLfloat w
[0]
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLsizei range
GLfloat GLfloat p
[1]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static const struct TessellationWindingOrderTab cw[]
#define emit
#define Q_UNUSED(x)
#define RANGE
static bool resizeHorizontalDirectionFixed
static bool resizeVerticalDirectionFixed
QFrame frame
[0]