Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qeglfsscreen.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// Qt-Security score:significant reason:default
4
5#include <QtCore/qtextstream.h>
6#include <QtGui/qwindow.h>
7#include <QtGui/private/qguiapplication_p.h>
8#include <qpa/qwindowsysteminterface.h>
9#include <qpa/qplatformcursor.h>
10#ifndef QT_NO_OPENGL
11# include <QtOpenGL/private/qopenglcompositor_p.h>
12#endif
13
14#include "qeglfsscreen_p.h"
15#include "qeglfswindow_p.h"
16#include "qeglfshooks_p.h"
17
19
20QEglFSScreen::QEglFSScreen(EGLDisplay dpy)
21 : m_dpy(dpy),
22 m_surface(EGL_NO_SURFACE),
23 m_cursor(nullptr)
24{
25 m_cursor = qt_egl_device_integration()->createCursor(this);
26}
27
28QEglFSScreen::~QEglFSScreen()
29{
30 delete m_cursor;
31}
32
33QRect QEglFSScreen::geometry() const
34{
35 QRect r = rawGeometry();
36
37 static int rotation = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ROTATION");
38 switch (rotation) {
39 case 0:
40 case 180:
41 case -180:
42 break;
43 case 90:
44 case -90: {
45 int h = r.height();
46 r.setHeight(r.width());
47 r.setWidth(h);
48 break;
49 }
50 default:
51 qWarning("Invalid rotation %d specified in QT_QPA_EGLFS_ROTATION", rotation);
52 break;
53 }
54
55 return r;
56}
57
58QRect QEglFSScreen::rawGeometry() const
59{
60 return QRect(QPoint(0, 0), qt_egl_device_integration()->screenSize());
61}
62
63int QEglFSScreen::depth() const
64{
65 return qt_egl_device_integration()->screenDepth();
66}
67
68QImage::Format QEglFSScreen::format() const
69{
70 return qt_egl_device_integration()->screenFormat();
71}
72
73QSizeF QEglFSScreen::physicalSize() const
74{
75 return qt_egl_device_integration()->physicalScreenSize();
76}
77
78QDpi QEglFSScreen::logicalDpi() const
79{
80 return qt_egl_device_integration()->logicalDpi();
81}
82
83QDpi QEglFSScreen::logicalBaseDpi() const
84{
85 return qt_egl_device_integration()->logicalBaseDpi();
86}
87
88Qt::ScreenOrientation QEglFSScreen::nativeOrientation() const
89{
90 return qt_egl_device_integration()->nativeOrientation();
91}
92
93Qt::ScreenOrientation QEglFSScreen::orientation() const
94{
95 return qt_egl_device_integration()->orientation();
96}
97
98QPlatformCursor *QEglFSScreen::cursor() const
99{
100 return m_cursor;
101}
102
103qreal QEglFSScreen::refreshRate() const
104{
105 return qt_egl_device_integration()->refreshRate();
106}
107
108void QEglFSScreen::setPrimarySurface(EGLSurface surface)
109{
110 m_surface = surface;
111}
112
113void QEglFSScreen::handleCursorMove(const QPoint &pos)
114{
115#ifndef QT_NO_OPENGL
116 const QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
117 const QList<QOpenGLCompositorWindow *> windows = compositor->windows();
118 QEglFSIntegration *platformIntegration = static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration());
119
120 // Generate enter and leave events like a real windowing system would do.
121 if (windows.isEmpty())
122 return;
123
124 // First window is always fullscreen.
125 if (windows.size() == 1) {
126 QWindow *window = windows[0]->sourceWindow();
127 if (platformIntegration->pointerWindow() != window) {
128 platformIntegration->setPointerWindow(window);
129 QWindowSystemInterface::handleEnterEvent(window, window->mapFromGlobal(pos), pos);
130 }
131 return;
132 }
133
134 QWindow *enter = nullptr, *leave = nullptr;
135 for (int i = windows.size() - 1; i >= 0; --i) {
136 QWindow *window = windows[i]->sourceWindow();
137 const QRect geom = window->geometry();
138 if (geom.contains(pos)) {
139 if (platformIntegration->pointerWindow() != window) {
140 leave = platformIntegration->pointerWindow();
141 platformIntegration->setPointerWindow(window);
142 enter = window;
143 }
144 break;
145 }
146 }
147
148 if (enter && leave) {
149 QWindowSystemInterface::handleEnterLeaveEvent(enter, leave, enter->mapFromGlobal(pos), pos);
150 } else if (enter) {
151 QWindowSystemInterface::handleEnterEvent(enter, enter->mapFromGlobal(pos), pos);
152 } else if (leave) {
153 QWindowSystemInterface::handleLeaveEvent(leave);
154 }
155#else
156 Q_UNUSED(pos);
157#endif
158}
159
160QPixmap QEglFSScreen::grabWindow(WId wid, int x, int y, int width, int height) const
161{
162#ifndef QT_NO_OPENGL
163 QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
164 const QList<QOpenGLCompositorWindow *> windows = compositor->windows();
165 Q_ASSERT(!windows.isEmpty());
166
167 QImage img;
168
169 QEglFSWindow *primaryWin = static_cast<QEglFSWindow *>(windows.first()->sourceWindow()->handle());
170 if (primaryWin->isRaster() || primaryWin->backingStore()) {
171 // Request the compositor to render everything into an FBO and read it back. This
172 // is of course slow, but it's safe and reliable. It will not include the mouse
173 // cursor, which is a plus.
174 img = compositor->grab();
175 } else {
176 // Just a single OpenGL window without compositing. Do not support this case for now. Doing
177 // glReadPixels is not an option since it would read from the back buffer which may have
178 // undefined content when calling right after a swapBuffers (unless preserved swap is
179 // available and enabled, but we have no support for that).
180 qWarning("grabWindow: Not supported for non-composited OpenGL content. Use QQuickWindow::grabWindow() instead.");
181 return QPixmap();
182 }
183
184 if (!wid) {
185 const QSize screenSize = geometry().size();
186 if (width < 0)
187 width = screenSize.width() - x;
188 if (height < 0)
189 height = screenSize.height() - y;
190 return QPixmap::fromImage(img).copy(x, y, width, height);
191 }
192
193 for (QOpenGLCompositorWindow *w : windows) {
194 const QWindow *window = w->sourceWindow();
195 if (window->winId() == wid) {
196 const QRect geom = window->geometry();
197 if (width < 0)
198 width = geom.width() - x;
199 if (height < 0)
200 height = geom.height() - y;
201 QRect rect(geom.topLeft() + QPoint(x, y), QSize(width, height));
202 rect &= window->geometry();
203 return QPixmap::fromImage(img).copy(rect);
204 }
205 }
206#else // QT_NO_OPENGL
207 Q_UNUSED(wid);
208 Q_UNUSED(x);
209 Q_UNUSED(y);
210 Q_UNUSED(width);
211 Q_UNUSED(height);
212#endif
213 return QPixmap();
214}
215
216QWindow *QEglFSScreen::topLevelAt(const QPoint &point) const
217{
218#ifndef QT_NO_OPENGL
219 QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
220 const QList<QOpenGLCompositorWindow *> windows = compositor->windows();
221 const int windowCount = windows.size();
222
223 // Higher z-order is at the end of the list
224 for (int i = windowCount - 1; i >= 0; i--) {
225 QWindow *window = windows[i]->sourceWindow();
226 if (window->isVisible() && window->geometry().contains(point))
227 return window;
228 }
229#endif
230
231 return QPlatformScreen::topLevelAt(point);
232}
233
234QT_END_NAMESPACE
Combined button and popup list for selecting options.