Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qeglfsx11integration.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
5#include <QThread>
6
7#include <X11/Xlib.h>
8#include <X11/Xlib-xcb.h>
9
10/* Make no mistake: This is not a replacement for the xcb platform plugin.
11 This here is barely an extremely useful tool for developing eglfs itself because
12 it allows to do so without any requirements for devices or drivers. */
13
15
16class EventReader : public QThread
17{
18public:
20 : m_integration(integration) { }
21
22 void run() override;
23
24private:
25 QEglFSX11Integration *m_integration;
26};
27
29
31{
32 xcb_generic_event_t *event = nullptr;
33 while (running.loadRelaxed() && (event = xcb_wait_for_event(m_integration->connection()))) {
34 uint response_type = event->response_type & ~0x80;
35 switch (response_type) {
36 case XCB_CLIENT_MESSAGE: {
37 xcb_client_message_event_t *client = (xcb_client_message_event_t *) event;
38 const xcb_atom_t *atoms = m_integration->atoms();
39 if (client->format == 32
40 && client->type == atoms[Atoms::WM_PROTOCOLS]
41 && client->data.data32[0] == atoms[Atoms::WM_DELETE_WINDOW]) {
42 QWindow *window = m_integration->platformWindow() ? m_integration->platformWindow()->window() : nullptr;
43 if (window)
45 }
46 break;
47 }
48 default:
49 break;
50 }
51 }
52}
53
54void QEglFSX11Integration::sendConnectionEvent(xcb_atom_t a)
55{
56 xcb_client_message_event_t event;
57 memset(&event, 0, sizeof(event));
58
59 event.response_type = XCB_CLIENT_MESSAGE;
60 event.format = 32;
61 event.sequence = 0;
62 event.window = m_connectionEventListener;
63 event.type = a;
64
65 xcb_send_event(m_connection, false, m_connectionEventListener, XCB_EVENT_MASK_NO_EVENT, (const char *)&event);
66 xcb_flush(m_connection);
67}
68
69#define DISPLAY ((Display *) m_display)
70
72{
73 m_display = XOpenDisplay(nullptr);
74 if (Q_UNLIKELY(!m_display))
75 qFatal("Could not open display");
76
77 XSetEventQueueOwner(DISPLAY, XCBOwnsEventQueue);
78 m_connection = XGetXCBConnection(DISPLAY);
79
80 running.ref();
81
82 xcb_screen_iterator_t it = xcb_setup_roots_iterator(xcb_get_setup(m_connection));
83
84 m_connectionEventListener = xcb_generate_id(m_connection);
85 xcb_create_window(m_connection, XCB_COPY_FROM_PARENT,
86 m_connectionEventListener, it.data->root,
87 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
88 it.data->root_visual, 0, nullptr);
89
90 m_eventReader = new EventReader(this);
91 m_eventReader->start();
92}
93
95{
96 running.deref();
97
98 sendConnectionEvent(XCB_ATOM_NONE);
99
100 m_eventReader->wait();
101 delete m_eventReader;
102 m_eventReader = nullptr;
103
104 XCloseDisplay(DISPLAY);
105 m_display = nullptr;
106 m_connection = nullptr;
107}
108
109EGLNativeDisplayType QEglFSX11Integration::platformDisplay() const
110{
111 return DISPLAY;
112}
113
115{
116 if (m_screenSize.isEmpty()) {
117 QList<QByteArray> env = qgetenv("EGLFS_X11_SIZE").split('x');
118 if (env.size() == 2) {
119 m_screenSize = QSize(env.at(0).toInt(), env.at(1).toInt());
120 } else {
121 XWindowAttributes a;
122 if (XGetWindowAttributes(DISPLAY, DefaultRootWindow(DISPLAY), &a))
123 m_screenSize = QSize(a.width, a.height);
124 }
125 }
126 return m_screenSize;
127}
128
130 const QSize &size,
131 const QSurfaceFormat &format)
132{
134
135 m_platformWindow = platformWindow;
136
137 xcb_screen_iterator_t it = xcb_setup_roots_iterator(xcb_get_setup(m_connection));
138 m_window = xcb_generate_id(m_connection);
139 xcb_create_window(m_connection, XCB_COPY_FROM_PARENT, m_window, it.data->root,
140 0, 0, size.width(), size.height(), 0,
141 XCB_WINDOW_CLASS_INPUT_OUTPUT, it.data->root_visual,
142 0, nullptr);
143
144 xcb_intern_atom_cookie_t cookies[Atoms::N_ATOMS];
145 static const char *atomNames[Atoms::N_ATOMS] = {
146 "_NET_WM_NAME",
147 "UTF8_STRING",
148 "WM_PROTOCOLS",
149 "WM_DELETE_WINDOW",
150 "_NET_WM_STATE",
151 "_NET_WM_STATE_FULLSCREEN"
152 };
153
154 for (int i = 0; i < Atoms::N_ATOMS; ++i) {
155 cookies[i] = xcb_intern_atom(m_connection, false, strlen(atomNames[i]), atomNames[i]);
156 xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(m_connection, cookies[i], nullptr);
157 m_atoms[i] = reply->atom;
158 free(reply);
159 }
160
161 // Set window title
162 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE, m_window,
163 m_atoms[Atoms::_NET_WM_NAME], m_atoms[Atoms::UTF8_STRING], 8, 5, "EGLFS");
164
165 // Enable WM_DELETE_WINDOW
166 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE, m_window,
167 m_atoms[Atoms::WM_PROTOCOLS], XCB_ATOM_ATOM, 32, 1, &m_atoms[Atoms::WM_DELETE_WINDOW]);
168
169 // Go fullscreen.
170 xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE, m_window,
171 m_atoms[Atoms::_NET_WM_STATE], XCB_ATOM_ATOM, 32, 1, &m_atoms[Atoms::_NET_WM_STATE_FULLSCREEN]);
172
173 xcb_map_window(m_connection, m_window);
174
175 xcb_flush(m_connection);
176
177 return qt_egl_cast<EGLNativeWindowType>(m_window);
178}
179
181{
182 xcb_destroy_window(m_connection, qt_egl_cast<xcb_window_t>(window));
183}
184
190
void run() override
EventReader(QEglFSX11Integration *integration)
xcb_connection_t * connection()
const xcb_atom_t * atoms() const
QPlatformWindow * platformWindow()
EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) override
EGLNativeDisplayType platformDisplay() const override
QSize screenSize() const override
bool hasCapability(QPlatformIntegration::Capability cap) const override
void destroyNativeWindow(EGLNativeWindowType window) override
Capability
Capabilities are used to determine specific features of a platform integration.
The QPlatformWindow class provides an abstraction for top-level windows.
QWindow * window() const
Returns the window which belongs to the QPlatformWindow.
\inmodule QtCore
Definition qsize.h:25
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
Definition qsize.h:124
The QSurfaceFormat class represents the format of a QSurface. \inmodule QtGui.
void start(Priority=InheritPriority)
Definition qthread.cpp:996
bool wait(QDeadlineTimer deadline=QDeadlineTimer(QDeadlineTimer::Forever))
Definition qthread.cpp:1023
static bool handleCloseEvent(QWindow *window)
\inmodule QtGui
Definition qwindow.h:63
QSet< QString >::iterator it
Combined button and popup list for selecting options.
#define Q_BASIC_ATOMIC_INITIALIZER(a)
#define Q_UNLIKELY(x)
static Q_CONSTINIT QBasicAtomicInt running
#define DISPLAY
#define qFatal
Definition qlogging.h:168
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum format
struct _cl_event * event
GLenum cap
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
#define Q_UNUSED(x)
unsigned int uint
Definition qtypes.h:34
aWidget window() -> setWindowTitle("New Window Title")
[2]
QNetworkReply * reply