KWin
Loading...
Searching...
No Matches
xcbutils.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org>
6 SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org>
7
8 SPDX-License-Identifier: GPL-2.0-or-later
9*/
10#include "utils/xcbutils.h"
11#include "utils/common.h"
12#include <core/output.h>
13#include <workspace.h>
14
15// Qt
16#include <QDebug>
17// xcb
18#include <cmath>
19#include <xcb/composite.h>
20#include <xcb/damage.h>
21#include <xcb/glx.h>
22#include <xcb/randr.h>
23#include <xcb/render.h>
24#include <xcb/shape.h>
25#include <xcb/sync.h>
26#include <xcb/xfixes.h>
27// system
28#include <sys/shm.h>
29#include <sys/types.h>
30
31namespace KWin
32{
33
34namespace Xcb
35{
36
37static const int COMPOSITE_MAX_MAJOR = 0;
38static const int COMPOSITE_MAX_MINOR = 4;
39static const int DAMAGE_MAX_MAJOR = 1;
40static const int DAMAGE_MIN_MAJOR = 1;
41static const int SYNC_MAX_MAJOR = 3;
42static const int SYNC_MAX_MINOR = 0;
43static const int RANDR_MAX_MAJOR = 1;
44static const int RANDR_MAX_MINOR = 4;
45static const int RENDER_MAX_MAJOR = 0;
46static const int RENDER_MAX_MINOR = 11;
47static const int XFIXES_MAX_MAJOR = 5;
48static const int XFIXES_MAX_MINOR = 0;
49
50QList<QByteArray> shapeOpCodes()
51{
52 // see https://www.x.org/releases/X11R7.7/doc/xextproto/shape.html
53 // extracted from <xcb/shape.h>
54 return QList<QByteArray>({QByteArrayLiteral("QueryVersion"),
55 QByteArrayLiteral("Rectangles"),
56 QByteArrayLiteral("Mask"),
57 QByteArrayLiteral("Combine"),
58 QByteArrayLiteral("Offset"),
59 QByteArrayLiteral("Extents"),
60 QByteArrayLiteral("Input"),
61 QByteArrayLiteral("InputSelected"),
62 QByteArrayLiteral("GetRectangles")});
63}
64
65QList<QByteArray> randrOpCodes()
66{
67 // see https://www.x.org/releases/X11R7.7/doc/randrproto/randrproto.txt
68 // extracted from <xcb/randr.h>
69 return QList<QByteArray>({QByteArrayLiteral("QueryVersion"),
70 QByteArray(""), // doesn't exist
71 QByteArrayLiteral("SetScreenConfig"),
72 QByteArray(""), // doesn't exits
73 QByteArrayLiteral("SelectInput"),
74 QByteArrayLiteral("GetScreenInfo"),
75 QByteArrayLiteral("GetScreenSizeRange"),
76 QByteArrayLiteral("SetScreenSize"),
77 QByteArrayLiteral("GetScreenResources"),
78 QByteArrayLiteral("GetOutputInfo"),
79 QByteArrayLiteral("ListOutputProperties"),
80 QByteArrayLiteral("QueryOutputProperty"),
81 QByteArrayLiteral("ConfigureOutputProperty"),
82 QByteArrayLiteral("ChangeOutputProperty"),
83 QByteArrayLiteral("DeleteOutputProperty"),
84 QByteArrayLiteral("GetOutputproperty"),
85 QByteArrayLiteral("CreateMode"),
86 QByteArrayLiteral("DestroyMode"),
87 QByteArrayLiteral("AddOutputMode"),
88 QByteArrayLiteral("DeleteOutputMode"),
89 QByteArrayLiteral("GetCrtcInfo"),
90 QByteArrayLiteral("SetCrtcConfig"),
91 QByteArrayLiteral("GetCrtcGammaSize"),
92 QByteArrayLiteral("GetCrtcGamma"),
93 QByteArrayLiteral("SetCrtcGamma"),
94 QByteArrayLiteral("GetScreenResourcesCurrent"),
95 QByteArrayLiteral("SetCrtcTransform"),
96 QByteArrayLiteral("GetCrtcTransform"),
97 QByteArrayLiteral("GetPanning"),
98 QByteArrayLiteral("SetPanning"),
99 QByteArrayLiteral("SetOutputPrimary"),
100 QByteArrayLiteral("GetOutputPrimary"),
101 QByteArrayLiteral("GetProviders"),
102 QByteArrayLiteral("GetProviderInfo"),
103 QByteArrayLiteral("SetProviderOffloadSink"),
104 QByteArrayLiteral("SetProviderOutputSource"),
105 QByteArrayLiteral("ListProviderProperties"),
106 QByteArrayLiteral("QueryProviderProperty"),
107 QByteArrayLiteral("ConfigureProviderroperty"),
108 QByteArrayLiteral("ChangeProviderProperty"),
109 QByteArrayLiteral("DeleteProviderProperty"),
110 QByteArrayLiteral("GetProviderProperty")});
111}
112
113QList<QByteArray> randrErrorCodes()
114{
115 // see https://www.x.org/releases/X11R7.7/doc/randrproto/randrproto.txt
116 // extracted from <xcb/randr.h>
117 return QList<QByteArray>({QByteArrayLiteral("BadOutput"),
118 QByteArrayLiteral("BadCrtc"),
119 QByteArrayLiteral("BadMode"),
120 QByteArrayLiteral("BadProvider")});
121}
122
123QList<QByteArray> damageOpCodes()
124{
125 // see https://www.x.org/releases/X11R7.7/doc/damageproto/damageproto.txt
126 // extracted from <xcb/damage.h>
127 return QList<QByteArray>({QByteArrayLiteral("QueryVersion"),
128 QByteArrayLiteral("Create"),
129 QByteArrayLiteral("Destroy"),
130 QByteArrayLiteral("Subtract"),
131 QByteArrayLiteral("Add")});
132}
133
134QList<QByteArray> damageErrorCodes()
135{
136 // see https://www.x.org/releases/X11R7.7/doc/damageproto/damageproto.txt
137 // extracted from <xcb/damage.h>
138 return QList<QByteArray>({QByteArrayLiteral("BadDamage")});
139}
140
141QList<QByteArray> compositeOpCodes()
142{
143 // see https://www.x.org/releases/X11R7.7/doc/compositeproto/compositeproto.txt
144 // extracted from <xcb/composite.h>
145 return QList<QByteArray>({QByteArrayLiteral("QueryVersion"),
146 QByteArrayLiteral("RedirectWindow"),
147 QByteArrayLiteral("RedirectSubwindows"),
148 QByteArrayLiteral("UnredirectWindow"),
149 QByteArrayLiteral("UnredirectSubwindows"),
150 QByteArrayLiteral("CreateRegionFromBorderClip"),
151 QByteArrayLiteral("NameWindowPixmap"),
152 QByteArrayLiteral("GetOverlayWindow"),
153 QByteArrayLiteral("ReleaseOverlayWindow")});
154}
155
156QList<QByteArray> fixesOpCodes()
157{
158 // see https://www.x.org/releases/X11R7.7/doc/fixesproto/fixesproto.txt
159 // extracted from <xcb/xfixes.h>
160 return QList<QByteArray>({QByteArrayLiteral("QueryVersion"),
161 QByteArrayLiteral("ChangeSaveSet"),
162 QByteArrayLiteral("SelectSelectionInput"),
163 QByteArrayLiteral("SelectCursorInput"),
164 QByteArrayLiteral("GetCursorImage"),
165 QByteArrayLiteral("CreateRegion"),
166 QByteArrayLiteral("CreateRegionFromBitmap"),
167 QByteArrayLiteral("CreateRegionFromWindow"),
168 QByteArrayLiteral("CreateRegionFromGc"),
169 QByteArrayLiteral("CreateRegionFromPicture"),
170 QByteArrayLiteral("DestroyRegion"),
171 QByteArrayLiteral("SetRegion"),
172 QByteArrayLiteral("CopyRegion"),
173 QByteArrayLiteral("UnionRegion"),
174 QByteArrayLiteral("IntersectRegion"),
175 QByteArrayLiteral("SubtractRegion"),
176 QByteArrayLiteral("InvertRegion"),
177 QByteArrayLiteral("TranslateRegion"),
178 QByteArrayLiteral("RegionExtents"),
179 QByteArrayLiteral("FetchRegion"),
180 QByteArrayLiteral("SetGcClipRegion"),
181 QByteArrayLiteral("SetWindowShapeRegion"),
182 QByteArrayLiteral("SetPictureClipRegion"),
183 QByteArrayLiteral("SetCursorName"),
184 QByteArrayLiteral("GetCursorName"),
185 QByteArrayLiteral("GetCursorImageAndName"),
186 QByteArrayLiteral("ChangeCursor"),
187 QByteArrayLiteral("ChangeCursorByName"),
188 QByteArrayLiteral("ExpandRegion"),
189 QByteArrayLiteral("HideCursor"),
190 QByteArrayLiteral("ShowCursor"),
191 QByteArrayLiteral("CreatePointerBarrier"),
192 QByteArrayLiteral("DeletePointerBarrier")});
193}
194
195QList<QByteArray> fixesErrorCodes()
196{
197 // see https://www.x.org/releases/X11R7.7/doc/fixesproto/fixesproto.txt
198 // extracted from <xcb/xfixes.h>
199 return QList<QByteArray>({QByteArrayLiteral("BadRegion")});
200}
201
202QList<QByteArray> renderOpCodes()
203{
204 // see https://www.x.org/releases/X11R7.7/doc/renderproto/renderproto.txt
205 // extracted from <xcb/render.h>
206 return QList<QByteArray>({QByteArrayLiteral("QueryVersion"),
207 QByteArrayLiteral("QueryPictFormats"),
208 QByteArrayLiteral("QueryPictIndexValues"),
209 QByteArrayLiteral("CreatePicture"),
210 QByteArrayLiteral("ChangePicture"),
211 QByteArrayLiteral("SetPictureClipRectangles"),
212 QByteArrayLiteral("FreePicture"),
213 QByteArrayLiteral("Composite"),
214 QByteArrayLiteral("Trapezoids"),
215 QByteArrayLiteral("Triangles"),
216 QByteArrayLiteral("TriStrip"),
217 QByteArrayLiteral("TriFan"),
218 QByteArrayLiteral("CreateGlyphSet"),
219 QByteArrayLiteral("ReferenceGlyphSet"),
220 QByteArrayLiteral("FreeGlyphSet"),
221 QByteArrayLiteral("AddGlyphs"),
222 QByteArrayLiteral("FreeGlyphs"),
223 QByteArrayLiteral("CompositeGlyphs8"),
224 QByteArrayLiteral("CompositeGlyphs16"),
225 QByteArrayLiteral("CompositeGlyphs32"),
226 QByteArrayLiteral("FillRectangles"),
227 QByteArrayLiteral("CreateCursor"),
228 QByteArrayLiteral("SetPictureTransform"),
229 QByteArrayLiteral("QueryFilters"),
230 QByteArrayLiteral("SetPictureFilter"),
231 QByteArrayLiteral("CreateAnimCursor"),
232 QByteArrayLiteral("AddTraps"),
233 QByteArrayLiteral("CreateSolidFill"),
234 QByteArrayLiteral("CreateLinearGradient"),
235 QByteArrayLiteral("CreateRadialGradient"),
236 QByteArrayLiteral("CreateConicalGradient")});
237}
238
239QList<QByteArray> syncOpCodes()
240{
241 // see https://www.x.org/releases/X11R7.7/doc/xextproto/sync.html
242 // extracted from <xcb/sync.h>
243 return QList<QByteArray>({QByteArrayLiteral("Initialize"),
244 QByteArrayLiteral("ListSystemCounters"),
245 QByteArrayLiteral("CreateCounter"),
246 QByteArrayLiteral("DestroyCounter"),
247 QByteArrayLiteral("QueryCounter"),
248 QByteArrayLiteral("Await"),
249 QByteArrayLiteral("ChangeCounter"),
250 QByteArrayLiteral("SetCounter"),
251 QByteArrayLiteral("CreateAlarm"),
252 QByteArrayLiteral("ChangeAlarm"),
253 QByteArrayLiteral("DestroyAlarm"),
254 QByteArrayLiteral("QueryAlarm"),
255 QByteArrayLiteral("SetPriority"),
256 QByteArrayLiteral("GetPriority"),
257 QByteArrayLiteral("CreateFence"),
258 QByteArrayLiteral("TriggerFence"),
259 QByteArrayLiteral("ResetFence"),
260 QByteArrayLiteral("DestroyFence"),
261 QByteArrayLiteral("QueryFence"),
262 QByteArrayLiteral("AwaitFence")});
263}
264
265static QList<QByteArray> glxOpCodes()
266{
267 return QList<QByteArray>{
268 QByteArrayLiteral(""),
269 QByteArrayLiteral("Render"),
270 QByteArrayLiteral("RenderLarge"),
271 QByteArrayLiteral("CreateContext"),
272 QByteArrayLiteral("DestroyContext"),
273 QByteArrayLiteral("MakeCurrent"),
274 QByteArrayLiteral("IsDirect"),
275 QByteArrayLiteral("QueryVersion"),
276 QByteArrayLiteral("WaitGL"),
277 QByteArrayLiteral("WaitX"),
278 QByteArrayLiteral("CopyContext"),
279 QByteArrayLiteral("SwapBuffers"),
280 QByteArrayLiteral("UseXFont"),
281 QByteArrayLiteral("CreateGLXPixmap"),
282 QByteArrayLiteral("GetVisualConfigs"),
283 QByteArrayLiteral("DestroyGLXPixmap"),
284 QByteArrayLiteral("VendorPrivate"),
285 QByteArrayLiteral("VendorPrivateWithReply"),
286 QByteArrayLiteral("QueryExtensionsString"),
287 QByteArrayLiteral("QueryServerString"),
288 QByteArrayLiteral("ClientInfo"),
289 QByteArrayLiteral("GetFBConfigs"),
290 QByteArrayLiteral("CreatePixmap"),
291 QByteArrayLiteral("DestroyPixmap"),
292 QByteArrayLiteral("CreateNewContext"),
293 QByteArrayLiteral("QueryContext"),
294 QByteArrayLiteral("MakeContextCurrent"),
295 QByteArrayLiteral("CreatePbuffer"),
296 QByteArrayLiteral("DestroyPbuffer"),
297 QByteArrayLiteral("GetDrawableAttributes"),
298 QByteArrayLiteral("ChangeDrawableAttributes"),
299 QByteArrayLiteral("CreateWindow"),
300 QByteArrayLiteral("DeleteWindow"),
301 QByteArrayLiteral("SetClientInfoARB"),
302 QByteArrayLiteral("CreateContextAttribsARB"),
303 QByteArrayLiteral("SetClientInfo2ARB")
304 // Opcodes 36-100 are unused
305 // The GL single commands begin at opcode 101
306 };
307}
308
309static QList<QByteArray> glxErrorCodes()
310{
311 return QList<QByteArray>{
312 QByteArrayLiteral("BadContext"),
313 QByteArrayLiteral("BadContextState"),
314 QByteArrayLiteral("BadDrawable"),
315 QByteArrayLiteral("BadPixmap"),
316 QByteArrayLiteral("BadContextTag"),
317 QByteArrayLiteral("BadCurrentWindow"),
318 QByteArrayLiteral("BadRenderRequest"),
319 QByteArrayLiteral("BadLargeRequest"),
320 QByteArrayLiteral("UnsupportedPrivateRequest"),
321 QByteArrayLiteral("BadFBConfig"),
322 QByteArrayLiteral("BadPbuffer"),
323 QByteArrayLiteral("BadCurrentDrawable"),
324 QByteArrayLiteral("BadWindow"),
325 QByteArrayLiteral("GLXBadProfileARB")};
326}
327
329 : version(0)
330 , eventBase(0)
331 , errorBase(0)
332 , majorOpcode(0)
333 , present(0)
334{
335}
336
337template<typename reply, typename T, typename F>
338void Extensions::initVersion(T cookie, F f, ExtensionData *dataToFill)
339{
340 UniqueCPtr<reply> version(f(connection(), cookie, nullptr));
341 dataToFill->version = version->major_version * 0x10 + version->minor_version;
342}
343
344Extensions *Extensions::s_self = nullptr;
345
347{
348 if (!s_self) {
349 s_self = new Extensions();
350 }
351 return s_self;
352}
353
355{
356 delete s_self;
357 s_self = nullptr;
358}
359
360Extensions::Extensions()
361{
362 init();
363}
364
365Extensions::~Extensions()
366{
367}
368
369void Extensions::init()
370{
371 xcb_connection_t *c = connection();
372 Q_ASSERT(c);
373 xcb_prefetch_extension_data(c, &xcb_shape_id);
374 xcb_prefetch_extension_data(c, &xcb_randr_id);
375 xcb_prefetch_extension_data(c, &xcb_damage_id);
376 xcb_prefetch_extension_data(c, &xcb_composite_id);
377 xcb_prefetch_extension_data(c, &xcb_xfixes_id);
378 xcb_prefetch_extension_data(c, &xcb_render_id);
379 xcb_prefetch_extension_data(c, &xcb_sync_id);
380 xcb_prefetch_extension_data(c, &xcb_glx_id);
381
382 m_shape.name = QByteArray("SHAPE");
383 m_randr.name = QByteArray("RANDR");
384 m_damage.name = QByteArray("DAMAGE");
385 m_composite.name = QByteArray("Composite");
386 m_fixes.name = QByteArray("XFIXES");
387 m_render.name = QByteArray("RENDER");
388 m_sync.name = QByteArray("SYNC");
389 m_glx.name = QByteArray("GLX");
390
391 m_shape.opCodes = shapeOpCodes();
392 m_randr.opCodes = randrOpCodes();
393 m_damage.opCodes = damageOpCodes();
394 m_composite.opCodes = compositeOpCodes();
395 m_fixes.opCodes = fixesOpCodes();
396 m_render.opCodes = renderOpCodes();
397 m_sync.opCodes = syncOpCodes();
398 m_glx.opCodes = glxOpCodes();
399
400 m_randr.errorCodes = randrErrorCodes();
401 m_damage.errorCodes = damageErrorCodes();
402 m_fixes.errorCodes = fixesErrorCodes();
403 m_glx.errorCodes = glxErrorCodes();
404
405 extensionQueryReply(xcb_get_extension_data(c, &xcb_shape_id), &m_shape);
406 extensionQueryReply(xcb_get_extension_data(c, &xcb_randr_id), &m_randr);
407 extensionQueryReply(xcb_get_extension_data(c, &xcb_damage_id), &m_damage);
408 extensionQueryReply(xcb_get_extension_data(c, &xcb_composite_id), &m_composite);
409 extensionQueryReply(xcb_get_extension_data(c, &xcb_xfixes_id), &m_fixes);
410 extensionQueryReply(xcb_get_extension_data(c, &xcb_render_id), &m_render);
411 extensionQueryReply(xcb_get_extension_data(c, &xcb_sync_id), &m_sync);
412 extensionQueryReply(xcb_get_extension_data(c, &xcb_glx_id), &m_glx);
413
414 // extension specific queries
415 xcb_shape_query_version_cookie_t shapeVersion;
416 xcb_randr_query_version_cookie_t randrVersion;
417 xcb_damage_query_version_cookie_t damageVersion;
418 xcb_composite_query_version_cookie_t compositeVersion;
419 xcb_xfixes_query_version_cookie_t xfixesVersion;
420 xcb_render_query_version_cookie_t renderVersion;
421 xcb_sync_initialize_cookie_t syncVersion;
422 if (m_shape.present) {
423 shapeVersion = xcb_shape_query_version_unchecked(c);
424 }
425 if (m_randr.present) {
426 randrVersion = xcb_randr_query_version_unchecked(c, RANDR_MAX_MAJOR, RANDR_MAX_MINOR);
427 xcb_randr_select_input(connection(), rootWindow(), XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);
428 }
429 if (m_damage.present) {
430 damageVersion = xcb_damage_query_version_unchecked(c, DAMAGE_MAX_MAJOR, DAMAGE_MIN_MAJOR);
431 }
432 if (m_composite.present) {
433 compositeVersion = xcb_composite_query_version_unchecked(c, COMPOSITE_MAX_MAJOR, COMPOSITE_MAX_MINOR);
434 }
435 if (m_fixes.present) {
436 xfixesVersion = xcb_xfixes_query_version_unchecked(c, XFIXES_MAX_MAJOR, XFIXES_MAX_MINOR);
437 }
438 if (m_render.present) {
439 renderVersion = xcb_render_query_version_unchecked(c, RENDER_MAX_MAJOR, RENDER_MAX_MINOR);
440 }
441 if (m_sync.present) {
442 syncVersion = xcb_sync_initialize(c, SYNC_MAX_MAJOR, SYNC_MAX_MINOR);
443 }
444 // handle replies
445 if (m_shape.present) {
446 initVersion<xcb_shape_query_version_reply_t>(shapeVersion, &xcb_shape_query_version_reply, &m_shape);
447 }
448 if (m_randr.present) {
449 initVersion<xcb_randr_query_version_reply_t>(randrVersion, &xcb_randr_query_version_reply, &m_randr);
450 }
451 if (m_damage.present) {
452 initVersion<xcb_damage_query_version_reply_t>(damageVersion, &xcb_damage_query_version_reply, &m_damage);
453 }
454 if (m_composite.present) {
455 initVersion<xcb_composite_query_version_reply_t>(compositeVersion, &xcb_composite_query_version_reply, &m_composite);
456 }
457 if (m_fixes.present) {
458 initVersion<xcb_xfixes_query_version_reply_t>(xfixesVersion, &xcb_xfixes_query_version_reply, &m_fixes);
459 }
460 if (m_render.present) {
461 initVersion<xcb_render_query_version_reply_t>(renderVersion, &xcb_render_query_version_reply, &m_render);
462 }
463 if (m_sync.present) {
464 initVersion<xcb_sync_initialize_reply_t>(syncVersion, &xcb_sync_initialize_reply, &m_sync);
465 }
466 qCDebug(KWIN_CORE) << "Extensions: shape: 0x" << QString::number(m_shape.version, 16)
467 << " composite: 0x" << QString::number(m_composite.version, 16)
468 << " render: 0x" << QString::number(m_render.version, 16)
469 << " fixes: 0x" << QString::number(m_fixes.version, 16)
470 << " randr: 0x" << QString::number(m_randr.version, 16)
471 << " sync: 0x" << QString::number(m_sync.version, 16)
472 << " damage: 0x " << QString::number(m_damage.version, 16);
473}
474
475void Extensions::extensionQueryReply(const xcb_query_extension_reply_t *extension, ExtensionData *dataToFill)
476{
477 if (!extension) {
478 return;
479 }
480 dataToFill->present = extension->present;
481 dataToFill->eventBase = extension->first_event;
482 dataToFill->errorBase = extension->first_error;
483 dataToFill->majorOpcode = extension->major_opcode;
484}
485
487{
488 return m_damage.eventBase + XCB_DAMAGE_NOTIFY;
489}
490
491bool Extensions::hasShape(xcb_window_t w) const
492{
493 if (!isShapeAvailable()) {
494 return false;
495 }
496 UniqueCPtr<xcb_shape_query_extents_reply_t> extents(xcb_shape_query_extents_reply(
497 connection(), xcb_shape_query_extents_unchecked(connection(), w), nullptr));
498 if (!extents) {
499 return false;
500 }
501 return extents->bounding_shaped > 0;
502}
503
505{
506 return m_composite.version >= 0x03; // 0.3
507}
508
510{
511 return m_fixes.version >= 0x30; // 3
512}
513
515{
516 return m_fixes.eventBase + XCB_XFIXES_CURSOR_NOTIFY;
517}
518
520{
521 return m_fixes.eventBase + XCB_XFIXES_SELECTION_NOTIFY;
522}
523
525{
526 return m_shape.version >= 0x11; // 1.1
527}
528
530{
531 return m_randr.eventBase + XCB_RANDR_SCREEN_CHANGE_NOTIFY;
532}
533
535{
536 return m_shape.eventBase + XCB_SHAPE_NOTIFY;
537}
538
540{
541 return m_sync.eventBase + XCB_SYNC_ALARM_NOTIFY;
542}
543
544QList<ExtensionData> Extensions::extensions() const
545{
546 return {
547 m_shape,
548 m_randr,
549 m_damage,
550 m_composite,
551 m_render,
552 m_fixes,
553 m_sync,
554 m_glx};
555}
556
557//****************************************
558// Shm
559//****************************************
561 : m_shmId(-1)
562 , m_buffer(nullptr)
563 , m_segment(XCB_NONE)
564 , m_valid(false)
565 , m_pixmapFormat(XCB_IMAGE_FORMAT_XY_BITMAP)
566{
567 m_valid = init();
568}
569
571{
572 if (m_valid) {
573 xcb_shm_detach(connection(), m_segment);
574 shmdt(m_buffer);
575 }
576}
577
578bool Shm::init()
579{
580 const xcb_query_extension_reply_t *ext = xcb_get_extension_data(connection(), &xcb_shm_id);
581 if (!ext || !ext->present) {
582 qCDebug(KWIN_CORE) << "SHM extension not available";
583 return false;
584 }
586 xcb_shm_query_version_unchecked(connection()), nullptr));
587 if (!version) {
588 qCDebug(KWIN_CORE) << "Failed to get SHM extension version information";
589 return false;
590 }
591 m_pixmapFormat = version->pixmap_format;
592 const int MAXSIZE = 4096 * 2048 * 4; // TODO check there are not larger windows
593 m_shmId = shmget(IPC_PRIVATE, MAXSIZE, IPC_CREAT | 0600);
594 if (m_shmId < 0) {
595 qCDebug(KWIN_CORE) << "Failed to allocate SHM segment";
596 return false;
597 }
598 m_buffer = shmat(m_shmId, nullptr, 0 /*read/write*/);
599 if (-1 == reinterpret_cast<long>(m_buffer)) {
600 qCDebug(KWIN_CORE) << "Failed to attach SHM segment";
601 shmctl(m_shmId, IPC_RMID, nullptr);
602 return false;
603 }
604 shmctl(m_shmId, IPC_RMID, nullptr);
605
606 m_segment = xcb_generate_id(connection());
607 const xcb_void_cookie_t cookie = xcb_shm_attach_checked(connection(), m_segment, m_shmId, false);
608 UniqueCPtr<xcb_generic_error_t> error(xcb_request_check(connection(), cookie));
609 if (error) {
610 qCDebug(KWIN_CORE) << "xcb_shm_attach error: " << error->error_code;
611 shmdt(m_buffer);
612 return false;
613 }
614
615 return true;
616}
617
618uint32_t toXNative(qreal value)
619{
620 //debug helper, check for things getting mangled
621 if (!qFuzzyIsNull(std::fmod(kwinApp()->xwaylandScale() * value, 1))) {
622 qCDebug(KWIN_CORE) << "precision lost! floating value sent to X" << kwinApp()->xwaylandScale() * value;
623 }
624 return std::round(kwinApp()->xwaylandScale() * value);
625}
626
627QRect toXNative(const QRectF &r)
628{
629 return QRect(toXNative(r.x()), toXNative(r.y()), toXNative(r.width()), toXNative(r.height()));
630}
631
632qreal fromXNative(int value)
633{
634 return value / kwinApp()->xwaylandScale();
635}
636
637QRectF fromXNative(const QRect &r)
638{
639 return QRectF(fromXNative(r.x()), fromXNative(r.y()), fromXNative(r.width()), fromXNative(r.height()));
640}
641
642QSizeF fromXNative(const QSize &s)
643{
644 return QSizeF(fromXNative(s.width()), fromXNative(s.height()));
645}
646
647static qreal nativeFloor(qreal value)
648{
649 return std::floor(value * kwinApp()->xwaylandScale()) / kwinApp()->xwaylandScale();
650}
651
652QRectF nativeFloor(const QRectF &rect)
653{
654 const auto output = workspace()->outputAt(rect.center());
655 const QRectF outputRect = output->mapFromGlobal(rect);
656 return output->mapToGlobal(QRectF(nativeFloor(outputRect.left()), nativeFloor(outputRect.top()),
657 nativeFloor(outputRect.width()), nativeFloor(outputRect.height())));
658}
659
660} // namespace Xcb
661} // namespace KWin
QRect mapFromGlobal(const QRect &rect) const
Definition output.cpp:425
Output * outputAt(const QPointF &pos) const
QList< QByteArray > errorCodes
Definition xcbutils.h:1466
QList< QByteArray > opCodes
Definition xcbutils.h:1465
bool isShapeInputAvailable() const
Definition xcbutils.cpp:524
bool isShapeAvailable() const
Definition xcbutils.h:1472
int fixesSelectionNotifyEvent() const
Definition xcbutils.cpp:519
QList< ExtensionData > extensions() const
Definition xcbutils.cpp:544
int damageNotifyEvent() const
Definition xcbutils.cpp:486
bool isCompositeOverlayAvailable() const
Definition xcbutils.cpp:504
int shapeNotifyEvent() const
Definition xcbutils.cpp:534
bool hasShape(xcb_window_t w) const
Definition xcbutils.cpp:491
static Extensions * self()
Definition xcbutils.cpp:346
static void destroy()
Definition xcbutils.cpp:354
bool isFixesRegionAvailable() const
Definition xcbutils.cpp:509
int fixesCursorNotifyEvent() const
Definition xcbutils.cpp:514
int syncAlarmNotifyEvent() const
Definition xcbutils.cpp:539
int randrNotifyEvent() const
Definition xcbutils.cpp:529
QList< QByteArray > damageErrorCodes()
Definition xcbutils.cpp:134
QList< QByteArray > fixesErrorCodes()
Definition xcbutils.cpp:195
qreal fromXNative(int value)
Definition xcbutils.cpp:632
QList< QByteArray > fixesOpCodes()
Definition xcbutils.cpp:156
QList< QByteArray > randrErrorCodes()
Definition xcbutils.cpp:113
QList< QByteArray > compositeOpCodes()
Definition xcbutils.cpp:141
uint32_t toXNative(qreal value)
Definition xcbutils.cpp:618
QList< QByteArray > renderOpCodes()
Definition xcbutils.cpp:202
QList< QByteArray > syncOpCodes()
Definition xcbutils.cpp:239
QList< QByteArray > randrOpCodes()
Definition xcbutils.cpp:65
QList< QByteArray > damageOpCodes()
Definition xcbutils.cpp:123
QList< QByteArray > shapeOpCodes()
Definition xcbutils.cpp:50
constexpr int version
KWIN_EXPORT xcb_window_t rootWindow()
Definition xcb.h:24
Workspace * workspace()
Definition workspace.h:830
KWIN_EXPORT xcb_connection_t * connection()
Definition xcb.h:19
std::unique_ptr< T, CDeleter > UniqueCPtr
Definition c_ptr.h:28