File indexing completed on 2025-03-16 08:15:01
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org> 0006 SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org> 0007 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 #include "utils/xcbutils.h" 0011 #include "utils/common.h" 0012 #include <core/output.h> 0013 #include <workspace.h> 0014 0015 // Qt 0016 #include <QDebug> 0017 // xcb 0018 #include <cmath> 0019 #include <xcb/composite.h> 0020 #include <xcb/damage.h> 0021 #include <xcb/glx.h> 0022 #include <xcb/randr.h> 0023 #include <xcb/render.h> 0024 #include <xcb/shape.h> 0025 #include <xcb/sync.h> 0026 #include <xcb/xfixes.h> 0027 // system 0028 #include <sys/shm.h> 0029 #include <sys/types.h> 0030 0031 namespace KWin 0032 { 0033 0034 namespace Xcb 0035 { 0036 0037 static const int COMPOSITE_MAX_MAJOR = 0; 0038 static const int COMPOSITE_MAX_MINOR = 4; 0039 static const int DAMAGE_MAX_MAJOR = 1; 0040 static const int DAMAGE_MIN_MAJOR = 1; 0041 static const int SYNC_MAX_MAJOR = 3; 0042 static const int SYNC_MAX_MINOR = 0; 0043 static const int RANDR_MAX_MAJOR = 1; 0044 static const int RANDR_MAX_MINOR = 4; 0045 static const int RENDER_MAX_MAJOR = 0; 0046 static const int RENDER_MAX_MINOR = 11; 0047 static const int XFIXES_MAX_MAJOR = 5; 0048 static const int XFIXES_MAX_MINOR = 0; 0049 0050 QList<QByteArray> shapeOpCodes() 0051 { 0052 // see https://www.x.org/releases/X11R7.7/doc/xextproto/shape.html 0053 // extracted from <xcb/shape.h> 0054 return QList<QByteArray>({QByteArrayLiteral("QueryVersion"), 0055 QByteArrayLiteral("Rectangles"), 0056 QByteArrayLiteral("Mask"), 0057 QByteArrayLiteral("Combine"), 0058 QByteArrayLiteral("Offset"), 0059 QByteArrayLiteral("Extents"), 0060 QByteArrayLiteral("Input"), 0061 QByteArrayLiteral("InputSelected"), 0062 QByteArrayLiteral("GetRectangles")}); 0063 } 0064 0065 QList<QByteArray> randrOpCodes() 0066 { 0067 // see https://www.x.org/releases/X11R7.7/doc/randrproto/randrproto.txt 0068 // extracted from <xcb/randr.h> 0069 return QList<QByteArray>({QByteArrayLiteral("QueryVersion"), 0070 QByteArray(""), // doesn't exist 0071 QByteArrayLiteral("SetScreenConfig"), 0072 QByteArray(""), // doesn't exits 0073 QByteArrayLiteral("SelectInput"), 0074 QByteArrayLiteral("GetScreenInfo"), 0075 QByteArrayLiteral("GetScreenSizeRange"), 0076 QByteArrayLiteral("SetScreenSize"), 0077 QByteArrayLiteral("GetScreenResources"), 0078 QByteArrayLiteral("GetOutputInfo"), 0079 QByteArrayLiteral("ListOutputProperties"), 0080 QByteArrayLiteral("QueryOutputProperty"), 0081 QByteArrayLiteral("ConfigureOutputProperty"), 0082 QByteArrayLiteral("ChangeOutputProperty"), 0083 QByteArrayLiteral("DeleteOutputProperty"), 0084 QByteArrayLiteral("GetOutputproperty"), 0085 QByteArrayLiteral("CreateMode"), 0086 QByteArrayLiteral("DestroyMode"), 0087 QByteArrayLiteral("AddOutputMode"), 0088 QByteArrayLiteral("DeleteOutputMode"), 0089 QByteArrayLiteral("GetCrtcInfo"), 0090 QByteArrayLiteral("SetCrtcConfig"), 0091 QByteArrayLiteral("GetCrtcGammaSize"), 0092 QByteArrayLiteral("GetCrtcGamma"), 0093 QByteArrayLiteral("SetCrtcGamma"), 0094 QByteArrayLiteral("GetScreenResourcesCurrent"), 0095 QByteArrayLiteral("SetCrtcTransform"), 0096 QByteArrayLiteral("GetCrtcTransform"), 0097 QByteArrayLiteral("GetPanning"), 0098 QByteArrayLiteral("SetPanning"), 0099 QByteArrayLiteral("SetOutputPrimary"), 0100 QByteArrayLiteral("GetOutputPrimary"), 0101 QByteArrayLiteral("GetProviders"), 0102 QByteArrayLiteral("GetProviderInfo"), 0103 QByteArrayLiteral("SetProviderOffloadSink"), 0104 QByteArrayLiteral("SetProviderOutputSource"), 0105 QByteArrayLiteral("ListProviderProperties"), 0106 QByteArrayLiteral("QueryProviderProperty"), 0107 QByteArrayLiteral("ConfigureProviderroperty"), 0108 QByteArrayLiteral("ChangeProviderProperty"), 0109 QByteArrayLiteral("DeleteProviderProperty"), 0110 QByteArrayLiteral("GetProviderProperty")}); 0111 } 0112 0113 QList<QByteArray> randrErrorCodes() 0114 { 0115 // see https://www.x.org/releases/X11R7.7/doc/randrproto/randrproto.txt 0116 // extracted from <xcb/randr.h> 0117 return QList<QByteArray>({QByteArrayLiteral("BadOutput"), 0118 QByteArrayLiteral("BadCrtc"), 0119 QByteArrayLiteral("BadMode"), 0120 QByteArrayLiteral("BadProvider")}); 0121 } 0122 0123 QList<QByteArray> damageOpCodes() 0124 { 0125 // see https://www.x.org/releases/X11R7.7/doc/damageproto/damageproto.txt 0126 // extracted from <xcb/damage.h> 0127 return QList<QByteArray>({QByteArrayLiteral("QueryVersion"), 0128 QByteArrayLiteral("Create"), 0129 QByteArrayLiteral("Destroy"), 0130 QByteArrayLiteral("Subtract"), 0131 QByteArrayLiteral("Add")}); 0132 } 0133 0134 QList<QByteArray> damageErrorCodes() 0135 { 0136 // see https://www.x.org/releases/X11R7.7/doc/damageproto/damageproto.txt 0137 // extracted from <xcb/damage.h> 0138 return QList<QByteArray>({QByteArrayLiteral("BadDamage")}); 0139 } 0140 0141 QList<QByteArray> compositeOpCodes() 0142 { 0143 // see https://www.x.org/releases/X11R7.7/doc/compositeproto/compositeproto.txt 0144 // extracted from <xcb/composite.h> 0145 return QList<QByteArray>({QByteArrayLiteral("QueryVersion"), 0146 QByteArrayLiteral("RedirectWindow"), 0147 QByteArrayLiteral("RedirectSubwindows"), 0148 QByteArrayLiteral("UnredirectWindow"), 0149 QByteArrayLiteral("UnredirectSubwindows"), 0150 QByteArrayLiteral("CreateRegionFromBorderClip"), 0151 QByteArrayLiteral("NameWindowPixmap"), 0152 QByteArrayLiteral("GetOverlayWindow"), 0153 QByteArrayLiteral("ReleaseOverlayWindow")}); 0154 } 0155 0156 QList<QByteArray> fixesOpCodes() 0157 { 0158 // see https://www.x.org/releases/X11R7.7/doc/fixesproto/fixesproto.txt 0159 // extracted from <xcb/xfixes.h> 0160 return QList<QByteArray>({QByteArrayLiteral("QueryVersion"), 0161 QByteArrayLiteral("ChangeSaveSet"), 0162 QByteArrayLiteral("SelectSelectionInput"), 0163 QByteArrayLiteral("SelectCursorInput"), 0164 QByteArrayLiteral("GetCursorImage"), 0165 QByteArrayLiteral("CreateRegion"), 0166 QByteArrayLiteral("CreateRegionFromBitmap"), 0167 QByteArrayLiteral("CreateRegionFromWindow"), 0168 QByteArrayLiteral("CreateRegionFromGc"), 0169 QByteArrayLiteral("CreateRegionFromPicture"), 0170 QByteArrayLiteral("DestroyRegion"), 0171 QByteArrayLiteral("SetRegion"), 0172 QByteArrayLiteral("CopyRegion"), 0173 QByteArrayLiteral("UnionRegion"), 0174 QByteArrayLiteral("IntersectRegion"), 0175 QByteArrayLiteral("SubtractRegion"), 0176 QByteArrayLiteral("InvertRegion"), 0177 QByteArrayLiteral("TranslateRegion"), 0178 QByteArrayLiteral("RegionExtents"), 0179 QByteArrayLiteral("FetchRegion"), 0180 QByteArrayLiteral("SetGcClipRegion"), 0181 QByteArrayLiteral("SetWindowShapeRegion"), 0182 QByteArrayLiteral("SetPictureClipRegion"), 0183 QByteArrayLiteral("SetCursorName"), 0184 QByteArrayLiteral("GetCursorName"), 0185 QByteArrayLiteral("GetCursorImageAndName"), 0186 QByteArrayLiteral("ChangeCursor"), 0187 QByteArrayLiteral("ChangeCursorByName"), 0188 QByteArrayLiteral("ExpandRegion"), 0189 QByteArrayLiteral("HideCursor"), 0190 QByteArrayLiteral("ShowCursor"), 0191 QByteArrayLiteral("CreatePointerBarrier"), 0192 QByteArrayLiteral("DeletePointerBarrier")}); 0193 } 0194 0195 QList<QByteArray> fixesErrorCodes() 0196 { 0197 // see https://www.x.org/releases/X11R7.7/doc/fixesproto/fixesproto.txt 0198 // extracted from <xcb/xfixes.h> 0199 return QList<QByteArray>({QByteArrayLiteral("BadRegion")}); 0200 } 0201 0202 QList<QByteArray> renderOpCodes() 0203 { 0204 // see https://www.x.org/releases/X11R7.7/doc/renderproto/renderproto.txt 0205 // extracted from <xcb/render.h> 0206 return QList<QByteArray>({QByteArrayLiteral("QueryVersion"), 0207 QByteArrayLiteral("QueryPictFormats"), 0208 QByteArrayLiteral("QueryPictIndexValues"), 0209 QByteArrayLiteral("CreatePicture"), 0210 QByteArrayLiteral("ChangePicture"), 0211 QByteArrayLiteral("SetPictureClipRectangles"), 0212 QByteArrayLiteral("FreePicture"), 0213 QByteArrayLiteral("Composite"), 0214 QByteArrayLiteral("Trapezoids"), 0215 QByteArrayLiteral("Triangles"), 0216 QByteArrayLiteral("TriStrip"), 0217 QByteArrayLiteral("TriFan"), 0218 QByteArrayLiteral("CreateGlyphSet"), 0219 QByteArrayLiteral("ReferenceGlyphSet"), 0220 QByteArrayLiteral("FreeGlyphSet"), 0221 QByteArrayLiteral("AddGlyphs"), 0222 QByteArrayLiteral("FreeGlyphs"), 0223 QByteArrayLiteral("CompositeGlyphs8"), 0224 QByteArrayLiteral("CompositeGlyphs16"), 0225 QByteArrayLiteral("CompositeGlyphs32"), 0226 QByteArrayLiteral("FillRectangles"), 0227 QByteArrayLiteral("CreateCursor"), 0228 QByteArrayLiteral("SetPictureTransform"), 0229 QByteArrayLiteral("QueryFilters"), 0230 QByteArrayLiteral("SetPictureFilter"), 0231 QByteArrayLiteral("CreateAnimCursor"), 0232 QByteArrayLiteral("AddTraps"), 0233 QByteArrayLiteral("CreateSolidFill"), 0234 QByteArrayLiteral("CreateLinearGradient"), 0235 QByteArrayLiteral("CreateRadialGradient"), 0236 QByteArrayLiteral("CreateConicalGradient")}); 0237 } 0238 0239 QList<QByteArray> syncOpCodes() 0240 { 0241 // see https://www.x.org/releases/X11R7.7/doc/xextproto/sync.html 0242 // extracted from <xcb/sync.h> 0243 return QList<QByteArray>({QByteArrayLiteral("Initialize"), 0244 QByteArrayLiteral("ListSystemCounters"), 0245 QByteArrayLiteral("CreateCounter"), 0246 QByteArrayLiteral("DestroyCounter"), 0247 QByteArrayLiteral("QueryCounter"), 0248 QByteArrayLiteral("Await"), 0249 QByteArrayLiteral("ChangeCounter"), 0250 QByteArrayLiteral("SetCounter"), 0251 QByteArrayLiteral("CreateAlarm"), 0252 QByteArrayLiteral("ChangeAlarm"), 0253 QByteArrayLiteral("DestroyAlarm"), 0254 QByteArrayLiteral("QueryAlarm"), 0255 QByteArrayLiteral("SetPriority"), 0256 QByteArrayLiteral("GetPriority"), 0257 QByteArrayLiteral("CreateFence"), 0258 QByteArrayLiteral("TriggerFence"), 0259 QByteArrayLiteral("ResetFence"), 0260 QByteArrayLiteral("DestroyFence"), 0261 QByteArrayLiteral("QueryFence"), 0262 QByteArrayLiteral("AwaitFence")}); 0263 } 0264 0265 static QList<QByteArray> glxOpCodes() 0266 { 0267 return QList<QByteArray>{ 0268 QByteArrayLiteral(""), 0269 QByteArrayLiteral("Render"), 0270 QByteArrayLiteral("RenderLarge"), 0271 QByteArrayLiteral("CreateContext"), 0272 QByteArrayLiteral("DestroyContext"), 0273 QByteArrayLiteral("MakeCurrent"), 0274 QByteArrayLiteral("IsDirect"), 0275 QByteArrayLiteral("QueryVersion"), 0276 QByteArrayLiteral("WaitGL"), 0277 QByteArrayLiteral("WaitX"), 0278 QByteArrayLiteral("CopyContext"), 0279 QByteArrayLiteral("SwapBuffers"), 0280 QByteArrayLiteral("UseXFont"), 0281 QByteArrayLiteral("CreateGLXPixmap"), 0282 QByteArrayLiteral("GetVisualConfigs"), 0283 QByteArrayLiteral("DestroyGLXPixmap"), 0284 QByteArrayLiteral("VendorPrivate"), 0285 QByteArrayLiteral("VendorPrivateWithReply"), 0286 QByteArrayLiteral("QueryExtensionsString"), 0287 QByteArrayLiteral("QueryServerString"), 0288 QByteArrayLiteral("ClientInfo"), 0289 QByteArrayLiteral("GetFBConfigs"), 0290 QByteArrayLiteral("CreatePixmap"), 0291 QByteArrayLiteral("DestroyPixmap"), 0292 QByteArrayLiteral("CreateNewContext"), 0293 QByteArrayLiteral("QueryContext"), 0294 QByteArrayLiteral("MakeContextCurrent"), 0295 QByteArrayLiteral("CreatePbuffer"), 0296 QByteArrayLiteral("DestroyPbuffer"), 0297 QByteArrayLiteral("GetDrawableAttributes"), 0298 QByteArrayLiteral("ChangeDrawableAttributes"), 0299 QByteArrayLiteral("CreateWindow"), 0300 QByteArrayLiteral("DeleteWindow"), 0301 QByteArrayLiteral("SetClientInfoARB"), 0302 QByteArrayLiteral("CreateContextAttribsARB"), 0303 QByteArrayLiteral("SetClientInfo2ARB") 0304 // Opcodes 36-100 are unused 0305 // The GL single commands begin at opcode 101 0306 }; 0307 } 0308 0309 static QList<QByteArray> glxErrorCodes() 0310 { 0311 return QList<QByteArray>{ 0312 QByteArrayLiteral("BadContext"), 0313 QByteArrayLiteral("BadContextState"), 0314 QByteArrayLiteral("BadDrawable"), 0315 QByteArrayLiteral("BadPixmap"), 0316 QByteArrayLiteral("BadContextTag"), 0317 QByteArrayLiteral("BadCurrentWindow"), 0318 QByteArrayLiteral("BadRenderRequest"), 0319 QByteArrayLiteral("BadLargeRequest"), 0320 QByteArrayLiteral("UnsupportedPrivateRequest"), 0321 QByteArrayLiteral("BadFBConfig"), 0322 QByteArrayLiteral("BadPbuffer"), 0323 QByteArrayLiteral("BadCurrentDrawable"), 0324 QByteArrayLiteral("BadWindow"), 0325 QByteArrayLiteral("GLXBadProfileARB")}; 0326 } 0327 0328 ExtensionData::ExtensionData() 0329 : version(0) 0330 , eventBase(0) 0331 , errorBase(0) 0332 , majorOpcode(0) 0333 , present(0) 0334 { 0335 } 0336 0337 template<typename reply, typename T, typename F> 0338 void Extensions::initVersion(T cookie, F f, ExtensionData *dataToFill) 0339 { 0340 UniqueCPtr<reply> version(f(connection(), cookie, nullptr)); 0341 dataToFill->version = version->major_version * 0x10 + version->minor_version; 0342 } 0343 0344 Extensions *Extensions::s_self = nullptr; 0345 0346 Extensions *Extensions::self() 0347 { 0348 if (!s_self) { 0349 s_self = new Extensions(); 0350 } 0351 return s_self; 0352 } 0353 0354 void Extensions::destroy() 0355 { 0356 delete s_self; 0357 s_self = nullptr; 0358 } 0359 0360 Extensions::Extensions() 0361 { 0362 init(); 0363 } 0364 0365 Extensions::~Extensions() 0366 { 0367 } 0368 0369 void Extensions::init() 0370 { 0371 xcb_connection_t *c = connection(); 0372 Q_ASSERT(c); 0373 xcb_prefetch_extension_data(c, &xcb_shape_id); 0374 xcb_prefetch_extension_data(c, &xcb_randr_id); 0375 xcb_prefetch_extension_data(c, &xcb_damage_id); 0376 xcb_prefetch_extension_data(c, &xcb_composite_id); 0377 xcb_prefetch_extension_data(c, &xcb_xfixes_id); 0378 xcb_prefetch_extension_data(c, &xcb_render_id); 0379 xcb_prefetch_extension_data(c, &xcb_sync_id); 0380 xcb_prefetch_extension_data(c, &xcb_glx_id); 0381 0382 m_shape.name = QByteArray("SHAPE"); 0383 m_randr.name = QByteArray("RANDR"); 0384 m_damage.name = QByteArray("DAMAGE"); 0385 m_composite.name = QByteArray("Composite"); 0386 m_fixes.name = QByteArray("XFIXES"); 0387 m_render.name = QByteArray("RENDER"); 0388 m_sync.name = QByteArray("SYNC"); 0389 m_glx.name = QByteArray("GLX"); 0390 0391 m_shape.opCodes = shapeOpCodes(); 0392 m_randr.opCodes = randrOpCodes(); 0393 m_damage.opCodes = damageOpCodes(); 0394 m_composite.opCodes = compositeOpCodes(); 0395 m_fixes.opCodes = fixesOpCodes(); 0396 m_render.opCodes = renderOpCodes(); 0397 m_sync.opCodes = syncOpCodes(); 0398 m_glx.opCodes = glxOpCodes(); 0399 0400 m_randr.errorCodes = randrErrorCodes(); 0401 m_damage.errorCodes = damageErrorCodes(); 0402 m_fixes.errorCodes = fixesErrorCodes(); 0403 m_glx.errorCodes = glxErrorCodes(); 0404 0405 extensionQueryReply(xcb_get_extension_data(c, &xcb_shape_id), &m_shape); 0406 extensionQueryReply(xcb_get_extension_data(c, &xcb_randr_id), &m_randr); 0407 extensionQueryReply(xcb_get_extension_data(c, &xcb_damage_id), &m_damage); 0408 extensionQueryReply(xcb_get_extension_data(c, &xcb_composite_id), &m_composite); 0409 extensionQueryReply(xcb_get_extension_data(c, &xcb_xfixes_id), &m_fixes); 0410 extensionQueryReply(xcb_get_extension_data(c, &xcb_render_id), &m_render); 0411 extensionQueryReply(xcb_get_extension_data(c, &xcb_sync_id), &m_sync); 0412 extensionQueryReply(xcb_get_extension_data(c, &xcb_glx_id), &m_glx); 0413 0414 // extension specific queries 0415 xcb_shape_query_version_cookie_t shapeVersion; 0416 xcb_randr_query_version_cookie_t randrVersion; 0417 xcb_damage_query_version_cookie_t damageVersion; 0418 xcb_composite_query_version_cookie_t compositeVersion; 0419 xcb_xfixes_query_version_cookie_t xfixesVersion; 0420 xcb_render_query_version_cookie_t renderVersion; 0421 xcb_sync_initialize_cookie_t syncVersion; 0422 if (m_shape.present) { 0423 shapeVersion = xcb_shape_query_version_unchecked(c); 0424 } 0425 if (m_randr.present) { 0426 randrVersion = xcb_randr_query_version_unchecked(c, RANDR_MAX_MAJOR, RANDR_MAX_MINOR); 0427 xcb_randr_select_input(connection(), rootWindow(), XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE); 0428 } 0429 if (m_damage.present) { 0430 damageVersion = xcb_damage_query_version_unchecked(c, DAMAGE_MAX_MAJOR, DAMAGE_MIN_MAJOR); 0431 } 0432 if (m_composite.present) { 0433 compositeVersion = xcb_composite_query_version_unchecked(c, COMPOSITE_MAX_MAJOR, COMPOSITE_MAX_MINOR); 0434 } 0435 if (m_fixes.present) { 0436 xfixesVersion = xcb_xfixes_query_version_unchecked(c, XFIXES_MAX_MAJOR, XFIXES_MAX_MINOR); 0437 } 0438 if (m_render.present) { 0439 renderVersion = xcb_render_query_version_unchecked(c, RENDER_MAX_MAJOR, RENDER_MAX_MINOR); 0440 } 0441 if (m_sync.present) { 0442 syncVersion = xcb_sync_initialize(c, SYNC_MAX_MAJOR, SYNC_MAX_MINOR); 0443 } 0444 // handle replies 0445 if (m_shape.present) { 0446 initVersion<xcb_shape_query_version_reply_t>(shapeVersion, &xcb_shape_query_version_reply, &m_shape); 0447 } 0448 if (m_randr.present) { 0449 initVersion<xcb_randr_query_version_reply_t>(randrVersion, &xcb_randr_query_version_reply, &m_randr); 0450 } 0451 if (m_damage.present) { 0452 initVersion<xcb_damage_query_version_reply_t>(damageVersion, &xcb_damage_query_version_reply, &m_damage); 0453 } 0454 if (m_composite.present) { 0455 initVersion<xcb_composite_query_version_reply_t>(compositeVersion, &xcb_composite_query_version_reply, &m_composite); 0456 } 0457 if (m_fixes.present) { 0458 initVersion<xcb_xfixes_query_version_reply_t>(xfixesVersion, &xcb_xfixes_query_version_reply, &m_fixes); 0459 } 0460 if (m_render.present) { 0461 initVersion<xcb_render_query_version_reply_t>(renderVersion, &xcb_render_query_version_reply, &m_render); 0462 } 0463 if (m_sync.present) { 0464 initVersion<xcb_sync_initialize_reply_t>(syncVersion, &xcb_sync_initialize_reply, &m_sync); 0465 } 0466 qCDebug(KWIN_CORE) << "Extensions: shape: 0x" << QString::number(m_shape.version, 16) 0467 << " composite: 0x" << QString::number(m_composite.version, 16) 0468 << " render: 0x" << QString::number(m_render.version, 16) 0469 << " fixes: 0x" << QString::number(m_fixes.version, 16) 0470 << " randr: 0x" << QString::number(m_randr.version, 16) 0471 << " sync: 0x" << QString::number(m_sync.version, 16) 0472 << " damage: 0x " << QString::number(m_damage.version, 16); 0473 } 0474 0475 void Extensions::extensionQueryReply(const xcb_query_extension_reply_t *extension, ExtensionData *dataToFill) 0476 { 0477 if (!extension) { 0478 return; 0479 } 0480 dataToFill->present = extension->present; 0481 dataToFill->eventBase = extension->first_event; 0482 dataToFill->errorBase = extension->first_error; 0483 dataToFill->majorOpcode = extension->major_opcode; 0484 } 0485 0486 int Extensions::damageNotifyEvent() const 0487 { 0488 return m_damage.eventBase + XCB_DAMAGE_NOTIFY; 0489 } 0490 0491 bool Extensions::hasShape(xcb_window_t w) const 0492 { 0493 if (!isShapeAvailable()) { 0494 return false; 0495 } 0496 UniqueCPtr<xcb_shape_query_extents_reply_t> extents(xcb_shape_query_extents_reply( 0497 connection(), xcb_shape_query_extents_unchecked(connection(), w), nullptr)); 0498 if (!extents) { 0499 return false; 0500 } 0501 return extents->bounding_shaped > 0; 0502 } 0503 0504 bool Extensions::isCompositeOverlayAvailable() const 0505 { 0506 return m_composite.version >= 0x03; // 0.3 0507 } 0508 0509 bool Extensions::isFixesRegionAvailable() const 0510 { 0511 return m_fixes.version >= 0x30; // 3 0512 } 0513 0514 int Extensions::fixesCursorNotifyEvent() const 0515 { 0516 return m_fixes.eventBase + XCB_XFIXES_CURSOR_NOTIFY; 0517 } 0518 0519 int Extensions::fixesSelectionNotifyEvent() const 0520 { 0521 return m_fixes.eventBase + XCB_XFIXES_SELECTION_NOTIFY; 0522 } 0523 0524 bool Extensions::isShapeInputAvailable() const 0525 { 0526 return m_shape.version >= 0x11; // 1.1 0527 } 0528 0529 int Extensions::randrNotifyEvent() const 0530 { 0531 return m_randr.eventBase + XCB_RANDR_SCREEN_CHANGE_NOTIFY; 0532 } 0533 0534 int Extensions::shapeNotifyEvent() const 0535 { 0536 return m_shape.eventBase + XCB_SHAPE_NOTIFY; 0537 } 0538 0539 int Extensions::syncAlarmNotifyEvent() const 0540 { 0541 return m_sync.eventBase + XCB_SYNC_ALARM_NOTIFY; 0542 } 0543 0544 QList<ExtensionData> Extensions::extensions() const 0545 { 0546 return { 0547 m_shape, 0548 m_randr, 0549 m_damage, 0550 m_composite, 0551 m_render, 0552 m_fixes, 0553 m_sync, 0554 m_glx}; 0555 } 0556 0557 //**************************************** 0558 // Shm 0559 //**************************************** 0560 Shm::Shm() 0561 : m_shmId(-1) 0562 , m_buffer(nullptr) 0563 , m_segment(XCB_NONE) 0564 , m_valid(false) 0565 , m_pixmapFormat(XCB_IMAGE_FORMAT_XY_BITMAP) 0566 { 0567 m_valid = init(); 0568 } 0569 0570 Shm::~Shm() 0571 { 0572 if (m_valid) { 0573 xcb_shm_detach(connection(), m_segment); 0574 shmdt(m_buffer); 0575 } 0576 } 0577 0578 bool Shm::init() 0579 { 0580 const xcb_query_extension_reply_t *ext = xcb_get_extension_data(connection(), &xcb_shm_id); 0581 if (!ext || !ext->present) { 0582 qCDebug(KWIN_CORE) << "SHM extension not available"; 0583 return false; 0584 } 0585 UniqueCPtr<xcb_shm_query_version_reply_t> version(xcb_shm_query_version_reply(connection(), 0586 xcb_shm_query_version_unchecked(connection()), nullptr)); 0587 if (!version) { 0588 qCDebug(KWIN_CORE) << "Failed to get SHM extension version information"; 0589 return false; 0590 } 0591 m_pixmapFormat = version->pixmap_format; 0592 const int MAXSIZE = 4096 * 2048 * 4; // TODO check there are not larger windows 0593 m_shmId = shmget(IPC_PRIVATE, MAXSIZE, IPC_CREAT | 0600); 0594 if (m_shmId < 0) { 0595 qCDebug(KWIN_CORE) << "Failed to allocate SHM segment"; 0596 return false; 0597 } 0598 m_buffer = shmat(m_shmId, nullptr, 0 /*read/write*/); 0599 if (-1 == reinterpret_cast<long>(m_buffer)) { 0600 qCDebug(KWIN_CORE) << "Failed to attach SHM segment"; 0601 shmctl(m_shmId, IPC_RMID, nullptr); 0602 return false; 0603 } 0604 shmctl(m_shmId, IPC_RMID, nullptr); 0605 0606 m_segment = xcb_generate_id(connection()); 0607 const xcb_void_cookie_t cookie = xcb_shm_attach_checked(connection(), m_segment, m_shmId, false); 0608 UniqueCPtr<xcb_generic_error_t> error(xcb_request_check(connection(), cookie)); 0609 if (error) { 0610 qCDebug(KWIN_CORE) << "xcb_shm_attach error: " << error->error_code; 0611 shmdt(m_buffer); 0612 return false; 0613 } 0614 0615 return true; 0616 } 0617 0618 uint32_t toXNative(qreal value) 0619 { 0620 //debug helper, check for things getting mangled 0621 if (!qFuzzyIsNull(std::fmod(kwinApp()->xwaylandScale() * value, 1))) { 0622 qCDebug(KWIN_CORE) << "precision lost! floating value sent to X" << kwinApp()->xwaylandScale() * value; 0623 } 0624 return std::round(kwinApp()->xwaylandScale() * value); 0625 } 0626 0627 QRect toXNative(const QRectF &r) 0628 { 0629 return QRect(toXNative(r.x()), toXNative(r.y()), toXNative(r.width()), toXNative(r.height())); 0630 } 0631 0632 qreal fromXNative(int value) 0633 { 0634 return value / kwinApp()->xwaylandScale(); 0635 } 0636 0637 QRectF fromXNative(const QRect &r) 0638 { 0639 return QRectF(fromXNative(r.x()), fromXNative(r.y()), fromXNative(r.width()), fromXNative(r.height())); 0640 } 0641 0642 QSizeF fromXNative(const QSize &s) 0643 { 0644 return QSizeF(fromXNative(s.width()), fromXNative(s.height())); 0645 } 0646 0647 static qreal nativeFloor(qreal value) 0648 { 0649 return std::floor(value * kwinApp()->xwaylandScale()) / kwinApp()->xwaylandScale(); 0650 } 0651 0652 QRectF nativeFloor(const QRectF &rect) 0653 { 0654 const auto output = workspace()->outputAt(rect.center()); 0655 const QRectF outputRect = output->mapFromGlobal(rect); 0656 return output->mapToGlobal(QRectF(nativeFloor(outputRect.left()), nativeFloor(outputRect.top()), 0657 nativeFloor(outputRect.width()), nativeFloor(outputRect.height()))); 0658 } 0659 0660 } // namespace Xcb 0661 } // namespace KWin