-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathQtComponent.cpp
More file actions
133 lines (104 loc) · 4.09 KB
/
QtComponent.cpp
File metadata and controls
133 lines (104 loc) · 4.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: BSD-3-Clause
#include "QtComponent.h"
#include <QtCore/qloggingcategory.h>
#include <QtGui/qwindow.h>
Q_LOGGING_CATEGORY(qtComponent, "juce.qt.component")
using namespace juce;
class QtComponent::Pimpl : public QObject, public ComponentMovementWatcher
{
public:
Pimpl(QWindow *w, Component& c)
: ComponentMovementWatcher(&c)
, window(w)
{
qCDebug(qtComponent) << "Creating component" << this;
window->installEventFilter(this);
// Pick up initial state
componentPeerChanged();
componentVisibilityChanged();
}
~Pimpl() override
{
qCDebug(qtComponent) << "Deleting component" << this;
}
void componentMovedOrResized(bool wasMoved, bool wasResized) override
{
Q_UNUSED(wasMoved);
Q_UNUSED(wasResized);
qCDebug(qtComponent) << "Component" << this << "moved or resized";
auto *component = getComponent();
if (!component->getWidth() || !component->getHeight()) {
// Pick up size from window if not explicitly set on component
auto size = window->size();
component->setSize(size.width(), size.height());
}
// FIXME: The other native components use the top level component here,
// which is weird, as the window is attached to our closest peer, so the
// coordinates should presumably be relative to that.
auto* peer = component->getPeer();
if (!peer)
return;
auto area = peer->getAreaCoveredBy(*component);
QRect geometry(area.getX(), area.getY(), area.getWidth(), area.getHeight());
qCDebug(qtComponent) << "New geometry is" << geometry;
window->setGeometry(geometry);
}
bool eventFilter(QObject *object, QEvent *event) override
{
if (object != window.get())
return false;
switch (event->type()) {
case QEvent::Resize:
case QEvent::Move: {
auto g = window->geometry();
Rectangle<int> bounds(g.x(), g.y(), g.width(), g.height());
auto *component = getComponent();
if (auto *peer = component->getPeer())
bounds = component->getLocalArea(&peer->getComponent(), bounds);
qCDebug(qtComponent) << "Component" << this << "observed"
<< event->type() << "with new geometry" << g;
getComponent()->setBounds(bounds);
break;
}
default:
break;
}
return false;
}
void componentPeerChanged() override
{
qCDebug(qtComponent) << "Component" << this << "peer changed";
auto *component = getComponent();
auto *peer = component->getPeer();
// Re-parent before resetting foreign window, so that
// the old foreign window doesn't destroy the window.
window->setParent(peer ? QWindow::fromWinId(WId(peer->getNativeHandle())) : nullptr);
foreignWindow.reset(window->parent());
// ComponentMovementWatcher::componentParentHierarchyChanged() calls
// componentMovedOrResized(true, true), but goes via the component overload,
// which bails out of the component bounds have not changed, which they may
// not have. The bounds of our wrapped component may still be dirty though,
// now that we have a new peer, so force a move/resize.
componentMovedOrResized(true, true);
}
void componentVisibilityChanged() override
{
qCDebug(qtComponent) << "Component" << this << "visibility changed";
window->setVisible(getComponent()->isShowing());
}
std::unique_ptr<QWindow> foreignWindow;
std::unique_ptr<QWindow> window;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Pimpl)
};
QtComponent::QtComponent() = default;
QtComponent::~QtComponent() = default;
void QtComponent::setWindow(QWindow *window)
{
if (window != getWindow())
pimpl.reset(window ? new Pimpl(window, *this) : nullptr);
}
QWindow *QtComponent::getWindow() const
{
return pimpl ? pimpl->window.get() : nullptr;
}