Changeset View
Changeset View
Standalone View
Standalone View
src/declarativeimports/core/windowthumbnail.cpp
Show First 20 Lines • Show All 131 Lines • ▼ Show 20 Line(s) | |||||
132 | WindowThumbnail::WindowThumbnail(QQuickItem *parent) | 132 | WindowThumbnail::WindowThumbnail(QQuickItem *parent) | ||
133 | : QQuickItem(parent) | 133 | : QQuickItem(parent) | ||
134 | , QAbstractNativeEventFilter() | 134 | , QAbstractNativeEventFilter() | ||
135 | , m_xcb(false) | 135 | , m_xcb(false) | ||
136 | , m_composite(false) | 136 | , m_composite(false) | ||
137 | , m_winId(0) | 137 | , m_winId(0) | ||
138 | , m_paintedSize(QSizeF()) | 138 | , m_paintedSize(QSizeF()) | ||
139 | , m_thumbnailAvailable(false) | 139 | , m_thumbnailAvailable(false) | ||
140 | , m_redirecting(false) | ||||
140 | , m_damaged(false) | 141 | , m_damaged(false) | ||
141 | , m_depth(0) | 142 | , m_depth(0) | ||
142 | #if HAVE_XCB_COMPOSITE | 143 | #if HAVE_XCB_COMPOSITE | ||
143 | , m_openGLFunctionsResolved(false) | 144 | , m_openGLFunctionsResolved(false) | ||
144 | , m_damageEventBase(0) | 145 | , m_damageEventBase(0) | ||
145 | , m_damage(XCB_NONE) | 146 | , m_damage(XCB_NONE) | ||
146 | , m_pixmap(XCB_PIXMAP_NONE) | 147 | , m_pixmap(XCB_PIXMAP_NONE) | ||
147 | , m_texture(0) | 148 | , m_texture(0) | ||
148 | #if HAVE_GLX | 149 | #if HAVE_GLX | ||
149 | , m_glxPixmap(XCB_PIXMAP_NONE) | 150 | , m_glxPixmap(XCB_PIXMAP_NONE) | ||
150 | , m_bindTexImage(nullptr) | 151 | , m_bindTexImage(nullptr) | ||
151 | , m_releaseTexImage(nullptr) | 152 | , m_releaseTexImage(nullptr) | ||
152 | #endif // HAVE_GLX | 153 | #endif // HAVE_GLX | ||
153 | #if HAVE_EGL | 154 | #if HAVE_EGL | ||
154 | , m_eglFunctionsResolved(false) | 155 | , m_eglFunctionsResolved(false) | ||
155 | , m_image(EGL_NO_IMAGE_KHR) | 156 | , m_image(EGL_NO_IMAGE_KHR) | ||
156 | , m_eglCreateImageKHR(nullptr) | 157 | , m_eglCreateImageKHR(nullptr) | ||
157 | , m_eglDestroyImageKHR(nullptr) | 158 | , m_eglDestroyImageKHR(nullptr) | ||
158 | , m_glEGLImageTargetTexture2DOES(nullptr) | 159 | , m_glEGLImageTargetTexture2DOES(nullptr) | ||
159 | #endif // HAVE_EGL | 160 | #endif // HAVE_EGL | ||
160 | #endif | 161 | #endif | ||
161 | { | 162 | { | ||
162 | setFlag(ItemHasContents); | 163 | setFlag(ItemHasContents); | ||
163 | connect(this, &QQuickItem::windowChanged, [this](QQuickWindow * window) { | 164 | | ||
164 | if (!window) { | | |||
165 | return; | | |||
166 | } | | |||
167 | // restart the redirection, it might not have been active yet | | |||
168 | stopRedirecting(); | | |||
169 | startRedirecting(); | | |||
170 | update(); | | |||
171 | }); | | |||
172 | connect(this, &QQuickItem::enabledChanged, [this]() { | | |||
173 | if (!isEnabled()) { | | |||
174 | stopRedirecting(); | | |||
175 | releaseResources(); | | |||
176 | } else if (isVisible()) { | | |||
177 | startRedirecting(); | | |||
178 | update(); | | |||
179 | } | | |||
180 | }); | | |||
181 | connect(this, &QQuickItem::visibleChanged, [this]() { | | |||
182 | if (!isVisible()) { | | |||
183 | stopRedirecting(); | | |||
184 | releaseResources(); | | |||
185 | } else if (isEnabled()) { | | |||
186 | startRedirecting(); | | |||
187 | update(); | | |||
188 | } | | |||
189 | }); | | |||
190 | if (QGuiApplication *gui = dynamic_cast<QGuiApplication *>(QCoreApplication::instance())) { | 165 | if (QGuiApplication *gui = dynamic_cast<QGuiApplication *>(QCoreApplication::instance())) { | ||
191 | m_xcb = (gui->platformName() == QStringLiteral("xcb")); | 166 | m_xcb = (gui->platformName() == QStringLiteral("xcb")); | ||
192 | if (m_xcb) { | 167 | if (m_xcb) { | ||
193 | gui->installNativeEventFilter(this); | 168 | gui->installNativeEventFilter(this); | ||
194 | #if HAVE_XCB_COMPOSITE | 169 | #if HAVE_XCB_COMPOSITE | ||
195 | xcb_connection_t *c = QX11Info::connection(); | 170 | xcb_connection_t *c = QX11Info::connection(); | ||
196 | xcb_prefetch_extension_data(c, &xcb_composite_id); | 171 | xcb_prefetch_extension_data(c, &xcb_composite_id); | ||
197 | const auto *compositeReply = xcb_get_extension_data(c, &xcb_composite_id); | 172 | const auto *compositeReply = xcb_get_extension_data(c, &xcb_composite_id); | ||
Show All 13 Lines | |||||
211 | WindowThumbnail::~WindowThumbnail() | 186 | WindowThumbnail::~WindowThumbnail() | ||
212 | { | 187 | { | ||
213 | if (m_xcb) { | 188 | if (m_xcb) { | ||
214 | QCoreApplication::instance()->removeNativeEventFilter(this); | 189 | QCoreApplication::instance()->removeNativeEventFilter(this); | ||
215 | stopRedirecting(); | 190 | stopRedirecting(); | ||
216 | } | 191 | } | ||
217 | } | 192 | } | ||
218 | 193 | | |||
194 | void WindowThumbnail::itemChange(ItemChange change, const ItemChangeData &data) | ||||
195 | { | ||||
196 | switch (change) { | ||||
197 | case ItemSceneChange: | ||||
198 | if (m_scene) { | ||||
199 | disconnect(m_scene.data(), &QWindow::visibleChanged, this, &WindowThumbnail::sceneVisibilityChanged); | ||||
200 | } | ||||
201 | m_scene = data.window; | ||||
202 | if (m_scene) { | ||||
203 | connect(m_scene.data(), &QWindow::visibleChanged, this, &WindowThumbnail::sceneVisibilityChanged); | ||||
204 | // restart the redirection, it might not have been active yet | ||||
205 | stopRedirecting(); | ||||
206 | if (startRedirecting()) { | ||||
207 | update(); | ||||
208 | } | ||||
209 | } | ||||
210 | break; | ||||
211 | | ||||
212 | case ItemEnabledHasChanged: | ||||
213 | Q_FALLTHROUGH(); | ||||
zzag: Do you actually need Q_FALLTHROUGH() here? | |||||
I fall through so I wanted to make it explicit. I would have put a // fallthrough comment otherwise broulik: I fall through so I wanted to make it explicit. I would have put a `// fallthrough` comment… | |||||
214 | case ItemVisibleHasChanged: | ||||
215 | if (data.boolValue) { | ||||
216 | if (startRedirecting()) { | ||||
217 | update(); | ||||
218 | } | ||||
219 | } else { | ||||
220 | stopRedirecting(); | ||||
221 | releaseResources(); | ||||
222 | } | ||||
223 | break; | ||||
224 | | ||||
225 | default: | ||||
226 | break; | ||||
227 | } | ||||
228 | } | ||||
229 | | ||||
219 | void WindowThumbnail::releaseResources() | 230 | void WindowThumbnail::releaseResources() | ||
220 | { | 231 | { | ||
221 | #if HAVE_XCB_COMPOSITE | 232 | #if HAVE_XCB_COMPOSITE | ||
222 | 233 | | |||
223 | #if HAVE_GLX && HAVE_EGL | 234 | #if HAVE_GLX && HAVE_EGL | ||
224 | //only one (or none) should be set, but never both | 235 | //only one (or none) should be set, but never both | ||
225 | Q_ASSERT(m_glxPixmap == XCB_PIXMAP_NONE || m_image == EGL_NO_IMAGE_KHR); | 236 | Q_ASSERT(m_glxPixmap == XCB_PIXMAP_NONE || m_image == EGL_NO_IMAGE_KHR); | ||
226 | #endif | 237 | #endif | ||
▲ Show 20 Lines • Show All 611 Lines • ▼ Show 20 Line(s) | 848 | #if HAVE_XCB_COMPOSITE | |||
838 | xcb_connection_t *c = QX11Info::connection(); | 849 | xcb_connection_t *c = QX11Info::connection(); | ||
839 | if (m_pixmap != XCB_PIXMAP_NONE) { | 850 | if (m_pixmap != XCB_PIXMAP_NONE) { | ||
840 | xcb_free_pixmap(c, m_pixmap); | 851 | xcb_free_pixmap(c, m_pixmap); | ||
841 | m_pixmap = XCB_PIXMAP_NONE; | 852 | m_pixmap = XCB_PIXMAP_NONE; | ||
842 | } | 853 | } | ||
843 | if (m_winId == XCB_WINDOW_NONE) { | 854 | if (m_winId == XCB_WINDOW_NONE) { | ||
844 | return; | 855 | return; | ||
845 | } | 856 | } | ||
857 | if (m_redirecting) { | ||||
846 | xcb_composite_unredirect_window(c, m_winId, XCB_COMPOSITE_REDIRECT_AUTOMATIC); | 858 | xcb_composite_unredirect_window(c, m_winId, XCB_COMPOSITE_REDIRECT_AUTOMATIC); | ||
859 | } | ||||
860 | m_redirecting = false; | ||||
847 | if (m_damage == XCB_NONE) { | 861 | if (m_damage == XCB_NONE) { | ||
848 | return; | 862 | return; | ||
849 | } | 863 | } | ||
850 | xcb_damage_destroy(c, m_damage); | 864 | xcb_damage_destroy(c, m_damage); | ||
851 | m_damage = XCB_NONE; | 865 | m_damage = XCB_NONE; | ||
852 | #endif | 866 | #endif | ||
853 | } | 867 | } | ||
854 | 868 | | |||
855 | void WindowThumbnail::startRedirecting() | 869 | bool WindowThumbnail::startRedirecting() | ||
856 | { | 870 | { | ||
857 | if (!m_xcb || !m_composite || !window() || window()->winId() == m_winId) { | 871 | if (!m_xcb || !m_composite || !window() || !window()->isVisible() || window()->winId() == m_winId || !isEnabled() || !isVisible()) { | ||
858 | return; | 872 | return false; | ||
859 | } | 873 | } | ||
860 | #if HAVE_XCB_COMPOSITE | 874 | #if HAVE_XCB_COMPOSITE | ||
861 | if (m_winId == XCB_WINDOW_NONE) { | 875 | if (m_winId == XCB_WINDOW_NONE) { | ||
862 | return; | 876 | return false; | ||
863 | } | 877 | } | ||
864 | xcb_connection_t *c = QX11Info::connection(); | 878 | xcb_connection_t *c = QX11Info::connection(); | ||
865 | 879 | | |||
866 | // need to get the window attributes for the existing event mask | 880 | // need to get the window attributes for the existing event mask | ||
867 | const auto attribsCookie = xcb_get_window_attributes_unchecked(c, m_winId); | 881 | const auto attribsCookie = xcb_get_window_attributes_unchecked(c, m_winId); | ||
868 | 882 | | |||
869 | // redirect the window | 883 | // redirect the window | ||
870 | xcb_composite_redirect_window(c, m_winId, XCB_COMPOSITE_REDIRECT_AUTOMATIC); | 884 | xcb_composite_redirect_window(c, m_winId, XCB_COMPOSITE_REDIRECT_AUTOMATIC); | ||
885 | m_redirecting = true; | ||||
871 | 886 | | |||
872 | // generate the damage handle | 887 | // generate the damage handle | ||
873 | m_damage = xcb_generate_id(c); | 888 | m_damage = xcb_generate_id(c); | ||
874 | xcb_damage_create(c, m_damage, m_winId, XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY); | 889 | xcb_damage_create(c, m_damage, m_winId, XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY); | ||
875 | 890 | | |||
876 | QScopedPointer<xcb_get_window_attributes_reply_t, QScopedPointerPodDeleter> attr(xcb_get_window_attributes_reply(c, attribsCookie, nullptr)); | 891 | QScopedPointer<xcb_get_window_attributes_reply_t, QScopedPointerPodDeleter> attr(xcb_get_window_attributes_reply(c, attribsCookie, nullptr)); | ||
877 | uint32_t events = XCB_EVENT_MASK_STRUCTURE_NOTIFY; | 892 | uint32_t events = XCB_EVENT_MASK_STRUCTURE_NOTIFY; | ||
878 | if (!attr.isNull()) { | 893 | if (!attr.isNull()) { | ||
879 | events = events | attr->your_event_mask; | 894 | events = events | attr->your_event_mask; | ||
880 | } | 895 | } | ||
881 | // the event mask will not be removed again. We cannot track whether another component also needs STRUCTURE_NOTIFY (e.g. KWindowSystem). | 896 | // the event mask will not be removed again. We cannot track whether another component also needs STRUCTURE_NOTIFY (e.g. KWindowSystem). | ||
882 | // if we would remove the event mask again, other areas will break. | 897 | // if we would remove the event mask again, other areas will break. | ||
883 | xcb_change_window_attributes(c, m_winId, XCB_CW_EVENT_MASK, &events); | 898 | xcb_change_window_attributes(c, m_winId, XCB_CW_EVENT_MASK, &events); | ||
884 | // force to update the texture | 899 | // force to update the texture | ||
885 | m_damaged = true; | 900 | m_damaged = true; | ||
901 | return true; | ||||
902 | #else | ||||
903 | return false; | ||||
886 | #endif | 904 | #endif | ||
887 | } | 905 | } | ||
888 | 906 | | |||
889 | 907 | | |||
890 | 908 | | |||
891 | void WindowThumbnail::setThumbnailAvailable(bool thumbnailAvailable) | 909 | void WindowThumbnail::setThumbnailAvailable(bool thumbnailAvailable) | ||
892 | { | 910 | { | ||
893 | if (m_thumbnailAvailable != thumbnailAvailable) { | 911 | if (m_thumbnailAvailable != thumbnailAvailable) { | ||
894 | m_thumbnailAvailable = thumbnailAvailable; | 912 | m_thumbnailAvailable = thumbnailAvailable; | ||
895 | emit thumbnailAvailableChanged(); | 913 | emit thumbnailAvailableChanged(); | ||
896 | } | 914 | } | ||
897 | } | 915 | } | ||
898 | 916 | | |||
917 | void WindowThumbnail::sceneVisibilityChanged(bool visible) | ||||
918 | { | ||||
919 | if (visible) { | ||||
920 | if (startRedirecting()) { | ||||
921 | update(); | ||||
922 | } | ||||
923 | } else { | ||||
924 | stopRedirecting(); | ||||
925 | releaseResources(); | ||||
926 | } | ||||
927 | } | ||||
928 | | ||||
899 | } // namespace | 929 | } // namespace |
Do you actually need Q_FALLTHROUGH() here?