QtCanpool 3.3.0
载入中...
搜索中...
未找到
windowcontext.cpp
浏览该文件的文档.
1
5#include "windowcontext_p.h"
6#include "windowkit_p.h"
7#include <QtGui/QPainter>
8#include <QtGui/QPen>
9#include <QtGui/QScreen>
10#include <memory>
11
13
14namespace
15{
16
17class WinIdChangeEventFilter : public QObject
18{
19public:
20 explicit WinIdChangeEventFilter(QObject *widget, WindowContext *ctx, QObject *parent = nullptr)
21 : QObject(parent)
22 , ctx(ctx)
23 {
24 widget->installEventFilter(this);
25 }
26protected:
27 bool eventFilter(QObject *obj, QEvent *event) override
28 {
29 Q_UNUSED(obj)
30 if (event->type() == QEvent::WinIdChange) {
31 ctx->notifyWinIdChange();
32 }
33 return false;
34 }
35protected:
36 WindowContext *ctx;
37};
38
39class WindowEventFilter : public QObject
40{
41public:
42 explicit WindowEventFilter(QWindow *window, WindowContext *ctx, QObject *parent = nullptr)
43 : QObject(parent)
44 , ctx(ctx)
45 , window(window)
46 {
47 window->installEventFilter(this);
48 }
49protected:
50 bool eventFilter(QObject *obj, QEvent *event) override
51 {
52 return ctx->sharedDispatch(obj, event);
53 }
54protected:
55 WindowContext *ctx;
56 QWindow *window;
57};
58
59}
60
61WindowContext::WindowContext() = default;
62
63WindowContext::~WindowContext() = default;
64
65void WindowContext::setup(QObject *host, WindowItemDelegate *delegate)
66{
67 if (m_host || !host || !delegate) {
68 return;
69 }
70 m_host = host;
71 m_delegate.reset(delegate);
72 m_winIdChangeEventFilter = std::make_unique<WinIdChangeEventFilter>(host, this);
73
74 m_windowHandle = m_delegate->hostWindow(m_host);
75 if (m_windowHandle) {
76 winIdChanged();
77 m_windowEventFilter = std::make_unique<WindowEventFilter>(m_windowHandle, this);
78 }
79}
80
81bool WindowContext::setHitTestVisible(const QObject *obj, bool visible)
82{
83 Q_ASSERT(obj);
84 if (!obj) {
85 return false;
86 }
87
88 if (visible) {
89 m_hitTestVisibleItems.insert(obj);
90 } else {
91 m_hitTestVisibleItems.remove(obj);
92 }
93 return true;
94}
95
96bool WindowContext::setSystemButton(WindowAgentBase::SystemButton button, QObject *obj)
97{
98 Q_ASSERT(button != WindowAgentBase::Unknown);
99 if (button == WindowAgentBase::Unknown) {
100 return false;
101 }
102
103 if (m_systemButtons[button] == obj) {
104 return false;
105 }
106 m_systemButtons[button] = obj;
107 return true;
108}
109
110void WindowContext::removeSystemButton(WindowAgentBase::SystemButton button)
111{
112 m_systemButtons[button] = nullptr;
113}
114
115bool WindowContext::setTitleBar(QObject *item)
116{
117 Q_ASSERT(item);
118 if (m_titleBar == item) {
119 return false;
120 }
121
122 if (m_titleBar) {
123 // Since the title bar is changed, all items inside it should be dereferenced right away
124 for (auto &button : m_systemButtons) {
125 button = nullptr;
126 }
127 m_hitTestVisibleItems.clear();
128 }
129
130 m_titleBar = item;
131 return true;
132}
133
134#ifdef Q_OS_MAC
135void WindowContext::setSystemButtonAreaCallback(const ScreenRectCallback &callback)
136{
137 m_systemButtonAreaCallback = callback;
138 virtual_hook(SystemButtonAreaChangedHook, nullptr);
139}
140#endif
141
142bool WindowContext::isInSystemButtons(const QPoint &pos, WindowAgentBase::SystemButton *button) const
143{
144 *button = WindowAgentBase::Unknown;
145 for (int i = WindowAgentBase::WindowIcon; i <= WindowAgentBase::Close; ++i) {
146 auto currentButton = m_systemButtons[i];
147 if (!currentButton || !m_delegate->isVisible(currentButton) || !m_delegate->isEnabled(currentButton)) {
148 continue;
149 }
150 if (m_delegate->mapGeometryToScene(currentButton).contains(pos)) {
151 *button = static_cast<WindowAgentBase::SystemButton>(i);
152 return true;
153 }
154 }
155 return false;
156}
157
158bool WindowContext::isInTitleBarDraggableArea(const QPoint &pos) const
159{
160 if (!m_titleBar) {
161 // There's no title bar at all, the mouse will always be in the client area.
162 return false;
163 }
164 if (!m_delegate->isVisible(m_titleBar) || !m_delegate->isEnabled(m_titleBar)) {
165 // The title bar is hidden or disabled for some reason, treat it as there's
166 // no title bar.
167 return false;
168 }
169 QRect windowRect = {QPoint(0, 0), m_windowHandle->size()};
170 QRect titleBarRect = m_delegate->mapGeometryToScene(m_titleBar);
171 if (!titleBarRect.intersects(windowRect)) {
172 // The title bar is totally outside the window for some reason,
173 // also treat it as there's no title bar.
174 return false;
175 }
176
177 if (!titleBarRect.contains(pos)) {
178 return false;
179 }
180
181 for (int i = WindowAgentBase::WindowIcon; i <= WindowAgentBase::Close; ++i) {
182 auto currentButton = m_systemButtons[i];
183 if (currentButton && m_delegate->isVisible(currentButton) && m_delegate->isEnabled(currentButton) &&
184 m_delegate->mapGeometryToScene(currentButton).contains(pos)) {
185 return false;
186 }
187 }
188
189 for (auto widget : m_hitTestVisibleItems) {
190 if (widget && m_delegate->isVisible(widget) && m_delegate->isEnabled(widget) &&
191 m_delegate->mapGeometryToScene(widget).contains(pos)) {
192 return false;
193 }
194 }
195 if (!m_captionClassNameList.isEmpty()) {
196 if (auto widget = m_delegate->childAt(m_titleBar, pos)) {
197 if (!isCaptionClassName(widget->metaObject()->className())) {
198 return false;
199 }
200 }
201 }
202
203 return true;
204}
205
206bool WindowContext::isCaptionClassName(const char *name) const
207{
208 foreach (const QString &cn, m_captionClassNameList) {
209 if (cn.compare(QLatin1String(name)) == 0) {
210 return true;
211 }
212 }
213 return false;
214}
215
216void WindowContext::addCaptionClassName(const QString &name)
217{
218 if (!m_captionClassNameList.contains(name)) {
219 m_captionClassNameList.append(name);
220 }
221}
222
223QString WindowContext::key() const
224{
225 return {};
226}
227
228QWK_USED static constexpr const struct {
229 const quint32 activeLight = MAKE_RGBA_COLOR(210, 233, 189, 226);
230 const quint32 activeDark = MAKE_RGBA_COLOR(177, 205, 190, 240);
231 const quint32 inactiveLight = MAKE_RGBA_COLOR(193, 195, 211, 203);
232 const quint32 inactiveDark = MAKE_RGBA_COLOR(240, 240, 250, 255);
233} kSampleColorSet;
234
235void WindowContext::virtual_hook(int id, void *data)
236{
237 switch (id) {
238 case CentralizeHook: {
239 if (!m_windowHandle)
240 return;
241
242 QRect screenGeometry = m_windowHandle->screen()->geometry();
243 int x = (screenGeometry.width() - m_windowHandle->width()) / 2;
244 int y = (screenGeometry.height() - m_windowHandle->height()) / 2;
245 QPoint pos(x, y);
246 pos += screenGeometry.topLeft();
247 m_windowHandle->setPosition(pos);
248 return;
249 }
250
251 case RaiseWindowHook: {
252 if (!m_windowHandle)
253 return;
254
255 m_delegate->setWindowVisible(m_host, true);
256 Qt::WindowStates state = m_delegate->getWindowState(m_host);
257 if (state & Qt::WindowMinimized) {
258 m_delegate->setWindowState(m_host, state & ~Qt::WindowMinimized);
259 }
260 m_delegate->bringWindowToTop(m_host);
261 return;
262 }
263
264 case DefaultColorsHook: {
265 auto &map = *static_cast<QMap<QString, QColor> *>(data);
266 map.clear();
267 map.insert(QStringLiteral("activeLight"), kSampleColorSet.activeLight);
268 map.insert(QStringLiteral("activeDark"), kSampleColorSet.activeDark);
269 map.insert(QStringLiteral("inactiveLight"), kSampleColorSet.inactiveLight);
270 map.insert(QStringLiteral("inactiveDark"), kSampleColorSet.inactiveDark);
271 return;
272 }
273
274 default:
275 break;
276 }
277}
278
279void WindowContext::showSystemMenu(const QPoint &pos)
280{
281 virtual_hook(ShowSystemMenuHook, &const_cast<QPoint &>(pos));
282}
283
284void WindowContext::notifyWinIdChange()
285{
286 auto oldWindow = m_windowHandle;
287 m_windowHandle = m_delegate->hostWindow(m_host);
288 if (oldWindow == m_windowHandle)
289 return;
290 m_windowEventFilter.reset();
291 winIdChanged();
292 if (m_windowHandle) {
293 m_windowEventFilter = std::make_unique<WindowEventFilter>(m_windowHandle, this);
294
295 // Refresh window attributes
296 auto attributes = m_windowAttributes;
297 m_windowAttributes.clear();
298 for (auto it = attributes.begin(); it != attributes.end(); ++it) {
299 if (!windowAttributeChanged(it.key(), it.value(), {})) {
300 continue;
301 }
302 m_windowAttributes.insert(it.key(), it.value());
303 }
304 }
305}
306
307QVariant WindowContext::windowAttribute(const QString &key) const
308{
309 return m_windowAttributes.value(key);
310}
311
312bool WindowContext::setWindowAttribute(const QString &key, const QVariant &attribute)
313{
314 auto it = m_windowAttributes.find(key);
315 if (it == m_windowAttributes.end()) {
316 if (!attribute.isValid()) {
317 return true;
318 }
319 if (!m_windowHandle || !windowAttributeChanged(key, attribute, {})) {
320 return false;
321 }
322 m_windowAttributes.insert(key, attribute);
323 return true;
324 }
325
326 if (it.value() == attribute)
327 return true;
328 if (!m_windowHandle || !windowAttributeChanged(key, attribute, it.value())) {
329 return false;
330 }
331
332 if (attribute.isValid()) {
333 it.value() = attribute;
334 } else {
335 m_windowAttributes.erase(it);
336 }
337 return true;
338}
339
340bool WindowContext::windowAttributeChanged(const QString &key, const QVariant &attribute, const QVariant &oldAttribute)
341{
342 Q_UNUSED(key);
343 Q_UNUSED(attribute);
344 Q_UNUSED(oldAttribute);
345 return false;
346}
347
std::function< QRect(const QSize &)> ScreenRectCallback
const char * name
Definition qxtheme.cpp:25
QColor window
QColor button
#define QX_WINDOW_END_NAMESPACE
#define QX_WINDOW_BEGIN_NAMESPACE
WindowContext * ctx
#define MAKE_RGBA_COLOR(r, g, b, a)
Definition windowkit_p.h:34
#define QWK_USED
Definition windowkit_p.h:44