QtCanpool 3.3.0
载入中...
搜索中...
未找到
windowcontext_qt.cpp
浏览该文件的文档.
1
5#include "windowcontext_p.h"
6#include "windowkit_p.h"
7#include "windowsystem_p.h"
8#include <QtCore/QDebug>
9#include <QScreen>
10
12
13static constexpr const quint8 kDefaultResizeBorderThickness = 8;
14
15static Qt::CursorShape calculateCursorShape(const QWindow *window, const QPoint &pos)
16{
17#ifdef Q_OS_MACOS
18 Q_UNUSED(window);
19 Q_UNUSED(pos);
20 return Qt::ArrowCursor;
21#else
22 Q_ASSERT(window);
23 if (!window) {
24 return Qt::ArrowCursor;
25 }
26 if (window->visibility() != QWindow::Windowed) {
27 return Qt::ArrowCursor;
28 }
29 const int x = pos.x();
30 const int y = pos.y();
31 const int w = window->width();
32 const int h = window->height();
33 if (((x < kDefaultResizeBorderThickness) && (y < kDefaultResizeBorderThickness)) ||
34 ((x >= (w - kDefaultResizeBorderThickness)) && (y >= (h - kDefaultResizeBorderThickness)))) {
35 return Qt::SizeFDiagCursor;
36 }
37 if (((x >= (w - kDefaultResizeBorderThickness)) && (y < kDefaultResizeBorderThickness)) ||
38 ((x < kDefaultResizeBorderThickness) && (y >= (h - kDefaultResizeBorderThickness)))) {
39 return Qt::SizeBDiagCursor;
40 }
41 if ((x < kDefaultResizeBorderThickness) || (x >= (w - kDefaultResizeBorderThickness))) {
42 return Qt::SizeHorCursor;
43 }
44 if ((y < kDefaultResizeBorderThickness) || (y >= (h - kDefaultResizeBorderThickness))) {
45 return Qt::SizeVerCursor;
46 }
47 return Qt::ArrowCursor;
48#endif
49}
50
51static inline Qt::Edges calculateWindowEdges(const QWindow *window, const QPoint &pos)
52{
53#ifdef Q_OS_MACOS
54 Q_UNUSED(window);
55 Q_UNUSED(pos);
56 return {};
57#else
58 Q_ASSERT(window);
59 if (!window) {
60 return {};
61 }
62 if (window->visibility() != QWindow::Windowed) {
63 return {};
64 }
65 Qt::Edges edges = {};
66 const int x = pos.x();
67 const int y = pos.y();
68 if (x < kDefaultResizeBorderThickness) {
69 edges |= Qt::LeftEdge;
70 }
71 if (x >= (window->width() - kDefaultResizeBorderThickness)) {
72 edges |= Qt::RightEdge;
73 }
74 if (y < kDefaultResizeBorderThickness) {
75 edges |= Qt::TopEdge;
76 }
77 if (y >= (window->height() - kDefaultResizeBorderThickness)) {
78 edges |= Qt::BottomEdge;
79 }
80 return edges;
81#endif
82}
83
84class QtWindowEventFilter : public WindowSharedEventFilter
85{
86public:
87 explicit QtWindowEventFilter(WindowContext *context);
88 ~QtWindowEventFilter() override;
89
90 enum WindowStatus {
91 Idle,
92 WaitingRelease,
93 PreparingMove,
94 Moving,
95 Resizing,
96 };
97protected:
98 bool sharedEventFilter(QObject *object, QEvent *event) override;
99private:
100 WindowContext *m_context;
101 bool m_cursorShapeChanged;
102 WindowStatus m_windowStatus;
103};
104
105QtWindowEventFilter::QtWindowEventFilter(WindowContext *context)
106 : m_context(context)
107 , m_cursorShapeChanged(false)
108 , m_windowStatus(Idle)
109{
110 m_context->installSharedEventFilter(this);
111}
112
113QtWindowEventFilter::~QtWindowEventFilter() = default;
114
115bool QtWindowEventFilter::sharedEventFilter(QObject *obj, QEvent *event)
116{
117 Q_UNUSED(obj)
118
119 auto host = m_context->host();
120 auto window = m_context->window();
121 auto delegate = m_context->delegate();
122
123 auto type = event->type();
124#ifdef Q_OS_WINDOWS
125 if (type == QEvent::WindowStateChange) {
126 Qt::WindowStates windowState = delegate->getWindowState(host);
127 if (windowState & Qt::WindowMaximized) {
128 // Prevents the window from becoming full screen
129 window->setGeometry(window->screen()->availableGeometry());
130 return true;
131 }
132 }
133#endif
134 if (type < QEvent::MouseButtonPress || type > QEvent::MouseMove) {
135 return false;
136 }
137 auto me = static_cast<const QMouseEvent *>(event);
138 bool fixedSize = delegate->isHostSizeFixed(host);
139
140 QPoint scenePos = getMouseEventScenePos(me);
141 QPoint globalPos = getMouseEventGlobalPos(me);
142
143 bool inTitleBar = m_context->isInTitleBarDraggableArea(scenePos);
144 switch (type) {
145 case QEvent::MouseButtonPress: {
146 switch (me->button()) {
147 case Qt::LeftButton: {
148 if (!fixedSize) {
149 Qt::Edges edges = calculateWindowEdges(window, scenePos);
150 if (edges != Qt::Edges()) {
151 m_windowStatus = Resizing;
152 startSystemResize(window, edges);
153 event->accept();
154 return true;
155 }
156 }
157 if (inTitleBar) {
158 // If we call startSystemMove() now but release the mouse without actual
159 // movement, there will be no MouseReleaseEvent, so we defer it when the
160 // mouse is actually moving for the first time
161 m_windowStatus = PreparingMove;
162 event->accept();
163 return true;
164 }
165 break;
166 }
167 case Qt::RightButton: {
168 m_context->showSystemMenu(globalPos);
169 break;
170 }
171 default:
172 break;
173 }
174 m_windowStatus = WaitingRelease;
175 break;
176 }
177
178 case QEvent::MouseButtonRelease: {
179 switch (m_windowStatus) {
180 case PreparingMove:
181 case Moving:
182 case Resizing: {
183 m_windowStatus = Idle;
184 event->accept();
185 return true;
186 }
187 case WaitingRelease: {
188 m_windowStatus = Idle;
189 break;
190 }
191 default: {
192 if (inTitleBar) {
193 event->accept();
194 return true;
195 }
196 break;
197 }
198 }
199 break;
200 }
201
202 case QEvent::MouseMove: {
203 switch (m_windowStatus) {
204 case Moving: {
205 return true;
206 }
207 case PreparingMove: {
208 m_windowStatus = Moving;
209 startSystemMove(window);
210 event->accept();
211 return true;
212 }
213 case Idle: {
214 if (!fixedSize) {
215 const Qt::CursorShape shape = calculateCursorShape(window, scenePos);
216 if (shape == Qt::ArrowCursor) {
217 if (m_cursorShapeChanged) {
218 delegate->restoreCursorShape(host);
219 m_cursorShapeChanged = false;
220 }
221 } else {
222 delegate->setCursorShape(host, shape);
223 m_cursorShapeChanged = true;
224 }
225 }
226 break;
227 }
228 default:
229 break;
230 }
231 break;
232 }
233
234 case QEvent::MouseButtonDblClick: {
235 if (me->button() == Qt::LeftButton && inTitleBar && !fixedSize) {
236 Qt::WindowStates windowState = delegate->getWindowState(host);
237 if (!(windowState & Qt::WindowFullScreen)) {
238 if (windowState & Qt::WindowMaximized) {
239 delegate->setWindowState(host, windowState & ~Qt::WindowMaximized);
240 } else {
241 delegate->setWindowState(host, windowState | Qt::WindowMaximized);
242 }
243 event->accept();
244 return true;
245 }
246 }
247 break;
248 }
249
250 default:
251 break;
252 }
253 return false;
254}
255
256WindowContextQt::WindowContextQt()
257 : WindowContext()
258{
259 qtWindowEventFilter = std::make_unique<QtWindowEventFilter>(this);
260}
261
263
264QString WindowContextQt::key() const
265{
266 return QStringLiteral("qt");
267}
268
269void WindowContextQt::virtual_hook(int id, void *data)
270{
272}
273
275{
276 if (!m_windowHandle) {
277 m_delegate->setWindowFlags(m_host, m_delegate->getWindowFlags(m_host) & ~Qt::FramelessWindowHint);
278 return;
279 }
280
281 // Allocate new resources
282 m_delegate->setWindowFlags(m_host, m_delegate->getWindowFlags(m_host) | Qt::FramelessWindowHint);
283}
284
std::unique_ptr< WindowSharedEventFilter > qtWindowEventFilter
void virtual_hook(int id, void *data) override
QString key() const override
virtual void virtual_hook(int id, void *data)
std::unique_ptr< WindowItemDelegate > m_delegate
QPoint getMouseEventGlobalPos(const QMouseEvent *event)
Definition windowkit_p.h:78
QPoint getMouseEventScenePos(const QMouseEvent *event)
Definition windowkit_p.h:69
QColor window
#define QX_WINDOW_END_NAMESPACE
#define QX_WINDOW_BEGIN_NAMESPACE