Changeset View
Changeset View
Standalone View
Standalone View
xwl/xwayland.cpp
Show All 13 Lines | |||||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | 16 | GNU General Public License for more details. | ||
17 | 17 | | |||
18 | You should have received a copy of the GNU General Public License | 18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program. If not, see <http://www.gnu.org/licenses/>. | 19 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | *********************************************************************/ | 20 | *********************************************************************/ | ||
21 | #include "xwayland.h" | 21 | #include "xwayland.h" | ||
22 | #include "databridge.h" | ||||
23 | | ||||
22 | #include "wayland_server.h" | 24 | #include "wayland_server.h" | ||
23 | #include "main_wayland.h" | 25 | #include "main_wayland.h" | ||
24 | #include "utils.h" | 26 | #include "utils.h" | ||
25 | 27 | | |||
26 | #include <KLocalizedString> | 28 | #include <KLocalizedString> | ||
27 | 29 | | |||
28 | #include "xcbutils.h" | 30 | #include "xcbutils.h" | ||
29 | 31 | | |||
Show All 34 Lines | 52 | { | |||
64 | // close our pipe | 66 | // close our pipe | ||
65 | close(pipe); | 67 | close(pipe); | ||
66 | } | 68 | } | ||
67 | 69 | | |||
68 | namespace KWin { | 70 | namespace KWin { | ||
69 | namespace Xwl | 71 | namespace Xwl | ||
70 | { | 72 | { | ||
71 | 73 | | |||
74 | Xwayland *s_self = nullptr; | ||||
75 | Xwayland* Xwayland::self() | ||||
76 | { | ||||
77 | return s_self; | ||||
78 | } | ||||
79 | | ||||
72 | Xwayland::Xwayland(ApplicationWaylandAbstract *app, QObject *parent) | 80 | Xwayland::Xwayland(ApplicationWaylandAbstract *app, QObject *parent) | ||
73 | : QObject(parent), | 81 | : QObject(parent), | ||
74 | m_app(app) | 82 | m_app(app) | ||
75 | { | 83 | { | ||
84 | s_self = this; | ||||
76 | } | 85 | } | ||
77 | 86 | | |||
78 | Xwayland::~Xwayland() | 87 | Xwayland::~Xwayland() | ||
79 | { | 88 | { | ||
80 | disconnect(m_xwaylandFailConnection); | 89 | disconnect(m_xwaylandFailConnection); | ||
81 | if (m_app->x11Connection()) { | 90 | if (m_app->x11Connection()) { | ||
82 | Xcb::setInputFocus(XCB_INPUT_FOCUS_POINTER_ROOT); | 91 | Xcb::setInputFocus(XCB_INPUT_FOCUS_POINTER_ROOT); | ||
83 | m_app->destroyAtoms(); | 92 | m_app->destroyAtoms(); | ||
84 | Q_EMIT m_app->x11ConnectionAboutToBeDestroyed(); | 93 | Q_EMIT m_app->x11ConnectionAboutToBeDestroyed(); | ||
85 | xcb_disconnect(m_app->x11Connection()); | 94 | xcb_disconnect(m_app->x11Connection()); | ||
86 | m_app->setX11Connection(nullptr); | 95 | m_app->setX11Connection(nullptr); | ||
87 | } | 96 | } | ||
88 | 97 | | |||
89 | if (m_xwaylandProcess) { | 98 | if (m_xwaylandProcess) { | ||
90 | m_xwaylandProcess->terminate(); | 99 | m_xwaylandProcess->terminate(); | ||
91 | while (m_xwaylandProcess->state() != QProcess::NotRunning) { | 100 | while (m_xwaylandProcess->state() != QProcess::NotRunning) { | ||
92 | m_app->processEvents(QEventLoop::WaitForMoreEvents); | 101 | m_app->processEvents(QEventLoop::WaitForMoreEvents); | ||
93 | } | 102 | } | ||
94 | waylandServer()->destroyXWaylandConnection(); | 103 | waylandServer()->destroyXWaylandConnection(); | ||
95 | } | 104 | } | ||
105 | s_self = nullptr; | ||||
96 | } | 106 | } | ||
97 | 107 | | |||
98 | void Xwayland::init() | 108 | void Xwayland::init() | ||
99 | { | 109 | { | ||
100 | int pipeFds[2]; | 110 | int pipeFds[2]; | ||
101 | if (pipe(pipeFds) != 0) { | 111 | if (pipe(pipeFds) != 0) { | ||
102 | std::cerr << "FATAL ERROR failed to create pipe to start Xwayland " << std::endl; | 112 | std::cerr << "FATAL ERROR failed to create pipe to start Xwayland " << std::endl; | ||
103 | Q_EMIT criticalError(1); | 113 | Q_EMIT criticalError(1); | ||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Line(s) | 168 | [this, xDisplayPipe] { | |||
161 | QObject::connect(watcher, &QFutureWatcher<void>::finished, watcher, &QFutureWatcher<void>::deleteLater, Qt::QueuedConnection); | 171 | QObject::connect(watcher, &QFutureWatcher<void>::finished, watcher, &QFutureWatcher<void>::deleteLater, Qt::QueuedConnection); | ||
162 | watcher->setFuture(QtConcurrent::run(readDisplay, xDisplayPipe)); | 172 | watcher->setFuture(QtConcurrent::run(readDisplay, xDisplayPipe)); | ||
163 | } | 173 | } | ||
164 | ); | 174 | ); | ||
165 | m_xwaylandProcess->start(); | 175 | m_xwaylandProcess->start(); | ||
166 | close(pipeFds[1]); | 176 | close(pipeFds[1]); | ||
167 | } | 177 | } | ||
168 | 178 | | |||
179 | void Xwayland::prepareDestroy() | ||||
180 | { | ||||
181 | delete m_dataBridge; | ||||
182 | m_dataBridge = nullptr; | ||||
183 | } | ||||
184 | | ||||
169 | void Xwayland::createX11Connection() | 185 | void Xwayland::createX11Connection() | ||
170 | { | 186 | { | ||
171 | int screenNumber = 0; | 187 | int screenNumber = 0; | ||
172 | xcb_connection_t *c = nullptr; | 188 | xcb_connection_t *c = nullptr; | ||
173 | if (m_xcbConnectionFd == -1) { | 189 | if (m_xcbConnectionFd == -1) { | ||
174 | c = xcb_connect(nullptr, &screenNumber); | 190 | c = xcb_connect(nullptr, &screenNumber); | ||
175 | } else { | 191 | } else { | ||
176 | c = xcb_connect_to_fd(m_xcbConnectionFd, nullptr); | 192 | c = xcb_connect_to_fd(m_xcbConnectionFd, nullptr); | ||
177 | } | 193 | } | ||
178 | if (int error = xcb_connection_has_error(c)) { | 194 | if (int error = xcb_connection_has_error(c)) { | ||
179 | std::cerr << "FATAL ERROR: Creating connection to XServer failed: " << error << std::endl; | 195 | std::cerr << "FATAL ERROR: Creating connection to XServer failed: " << error << std::endl; | ||
180 | Q_EMIT criticalError(1); | 196 | Q_EMIT criticalError(1); | ||
181 | return; | 197 | return; | ||
182 | } | 198 | } | ||
183 | 199 | | |||
200 | xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xcb_get_setup(c)); | ||||
201 | m_xcbScreen = iter.data; | ||||
202 | Q_ASSERT(m_xcbScreen); | ||||
203 | | ||||
184 | m_app->setX11Connection(c); | 204 | m_app->setX11Connection(c); | ||
185 | // we don't support X11 multi-head in Wayland | 205 | // we don't support X11 multi-head in Wayland | ||
186 | m_app->setX11ScreenNumber(screenNumber); | 206 | m_app->setX11ScreenNumber(screenNumber); | ||
187 | m_app->setX11RootWindow(defaultScreen()->root); | 207 | m_app->setX11RootWindow(defaultScreen()->root); | ||
188 | } | 208 | } | ||
189 | 209 | | |||
190 | void Xwayland::continueStartupWithX() | 210 | void Xwayland::continueStartupWithX() | ||
191 | { | 211 | { | ||
192 | createX11Connection(); | 212 | createX11Connection(); | ||
193 | auto *xcbConn = m_app->x11Connection(); | 213 | auto *xcbConn = m_app->x11Connection(); | ||
194 | if (!xcbConn) { | 214 | if (!xcbConn) { | ||
195 | // about to quit | 215 | // about to quit | ||
196 | Q_EMIT criticalError(1); | 216 | Q_EMIT criticalError(1); | ||
197 | return; | 217 | return; | ||
198 | } | 218 | } | ||
199 | QSocketNotifier *notifier = new QSocketNotifier(xcb_get_file_descriptor(xcbConn), QSocketNotifier::Read, this); | 219 | QSocketNotifier *notifier = new QSocketNotifier(xcb_get_file_descriptor(xcbConn), QSocketNotifier::Read, this); | ||
200 | auto processXcbEvents = [this, xcbConn] { | 220 | auto processXcbEvents = [this, xcbConn] { | ||
201 | while (auto event = xcb_poll_for_event(xcbConn)) { | 221 | while (auto event = xcb_poll_for_event(xcbConn)) { | ||
222 | if (m_dataBridge->filterEvent(event)) { | ||||
223 | free(event); | ||||
224 | continue; | ||||
225 | } | ||||
202 | long result = 0; | 226 | long result = 0; | ||
203 | QThread::currentThread()->eventDispatcher()->filterNativeEvent(QByteArrayLiteral("xcb_generic_event_t"), event, &result); | 227 | QThread::currentThread()->eventDispatcher()->filterNativeEvent(QByteArrayLiteral("xcb_generic_event_t"), event, &result); | ||
204 | free(event); | 228 | free(event); | ||
205 | } | 229 | } | ||
206 | xcb_flush(xcbConn); | 230 | xcb_flush(xcbConn); | ||
207 | }; | 231 | }; | ||
208 | connect(notifier, &QSocketNotifier::activated, this, processXcbEvents); | 232 | connect(notifier, &QSocketNotifier::activated, this, processXcbEvents); | ||
209 | connect(QThread::currentThread()->eventDispatcher(), &QAbstractEventDispatcher::aboutToBlock, this, processXcbEvents); | 233 | connect(QThread::currentThread()->eventDispatcher(), &QAbstractEventDispatcher::aboutToBlock, this, processXcbEvents); | ||
210 | connect(QThread::currentThread()->eventDispatcher(), &QAbstractEventDispatcher::awake, this, processXcbEvents); | 234 | connect(QThread::currentThread()->eventDispatcher(), &QAbstractEventDispatcher::awake, this, processXcbEvents); | ||
211 | 235 | | |||
236 | xcb_prefetch_extension_data(xcbConn, &xcb_xfixes_id); | ||||
237 | m_xfixes = xcb_get_extension_data(xcbConn, &xcb_xfixes_id); | ||||
238 | | ||||
212 | // create selection owner for WM_S0 - magic X display number expected by XWayland | 239 | // create selection owner for WM_S0 - magic X display number expected by XWayland | ||
213 | KSelectionOwner owner("WM_S0", xcbConn, m_app->x11RootWindow()); | 240 | KSelectionOwner owner("WM_S0", xcbConn, m_app->x11RootWindow()); | ||
214 | owner.claim(true); | 241 | owner.claim(true); | ||
215 | 242 | | |||
216 | m_app->createAtoms(); | 243 | m_app->createAtoms(); | ||
217 | m_app->setupEventFilters(); | 244 | m_app->setupEventFilters(); | ||
218 | 245 | | |||
246 | m_dataBridge = new DataBridge; | ||||
247 | | ||||
219 | // Check whether another windowmanager is running | 248 | // Check whether another windowmanager is running | ||
220 | const uint32_t maskValues[] = {XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT}; | 249 | const uint32_t maskValues[] = {XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT}; | ||
221 | ScopedCPointer<xcb_generic_error_t> redirectCheck(xcb_request_check(connection(), | 250 | ScopedCPointer<xcb_generic_error_t> redirectCheck(xcb_request_check(connection(), | ||
222 | xcb_change_window_attributes_checked(connection(), | 251 | xcb_change_window_attributes_checked(connection(), | ||
223 | rootWindow(), | 252 | rootWindow(), | ||
224 | XCB_CW_EVENT_MASK, | 253 | XCB_CW_EVENT_MASK, | ||
225 | maskValues))); | 254 | maskValues))); | ||
226 | if (!redirectCheck.isNull()) { | 255 | if (!redirectCheck.isNull()) { | ||
Show All 19 Lines |