You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
620 lines
25 KiB
620 lines
25 KiB
/******************************************************************** |
|
KWin - the KDE window manager |
|
This file is part of the KDE project. |
|
|
|
Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org> |
|
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org> |
|
|
|
This program is free software; you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation; either version 2 of the License, or |
|
(at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
*********************************************************************/ |
|
#include "xcbutils.h" |
|
#include "utils.h" |
|
// Qt |
|
#include <QDebug> |
|
// xcb |
|
#include <xcb/composite.h> |
|
#include <xcb/damage.h> |
|
#include <xcb/randr.h> |
|
#include <xcb/render.h> |
|
#include <xcb/shape.h> |
|
#include <xcb/sync.h> |
|
#include <xcb/xfixes.h> |
|
#include <xcb/glx.h> |
|
// system |
|
#include <sys/shm.h> |
|
#include <sys/types.h> |
|
|
|
namespace KWin { |
|
|
|
namespace Xcb { |
|
|
|
static const int COMPOSITE_MAX_MAJOR = 0; |
|
static const int COMPOSITE_MAX_MINOR = 4; |
|
static const int DAMAGE_MAX_MAJOR = 1; |
|
static const int DAMAGE_MIN_MAJOR = 1; |
|
static const int SYNC_MAX_MAJOR = 3; |
|
static const int SYNC_MAX_MINOR = 0; |
|
static const int RANDR_MAX_MAJOR = 1; |
|
static const int RANDR_MAX_MINOR = 4; |
|
static const int RENDER_MAX_MAJOR = 0; |
|
static const int RENDER_MAX_MINOR = 11; |
|
static const int XFIXES_MAX_MAJOR = 5; |
|
static const int XFIXES_MAX_MINOR = 0; |
|
|
|
QVector<QByteArray> shapeOpCodes() |
|
{ |
|
// see https://www.x.org/releases/X11R7.7/doc/xextproto/shape.html |
|
// extracted from <xcb/shape.h> |
|
return QVector<QByteArray>({QByteArrayLiteral("QueryVersion"), |
|
QByteArrayLiteral("Rectangles"), |
|
QByteArrayLiteral("Mask"), |
|
QByteArrayLiteral("Combine"), |
|
QByteArrayLiteral("Offset"), |
|
QByteArrayLiteral("Extents"), |
|
QByteArrayLiteral("Input"), |
|
QByteArrayLiteral("InputSelected"), |
|
QByteArrayLiteral("GetRectangles")}); |
|
} |
|
|
|
QVector<QByteArray> randrOpCodes() |
|
{ |
|
// see https://www.x.org/releases/X11R7.7/doc/randrproto/randrproto.txt |
|
// extracted from <xcb/randr.h> |
|
return QVector<QByteArray>({QByteArrayLiteral("QueryVersion"), |
|
QByteArray(""), // doesn't exist |
|
QByteArrayLiteral("SetScreenConfig"), |
|
QByteArray(""), // doesn't exits |
|
QByteArrayLiteral("SelectInput"), |
|
QByteArrayLiteral("GetScreenInfo"), |
|
QByteArrayLiteral("GetScreenSizeRange"), |
|
QByteArrayLiteral("SetScreenSize"), |
|
QByteArrayLiteral("GetScreenResources"), |
|
QByteArrayLiteral("GetOutputInfo"), |
|
QByteArrayLiteral("ListOutputProperties"), |
|
QByteArrayLiteral("QueryOutputProperty"), |
|
QByteArrayLiteral("ConfigureOutputProperty"), |
|
QByteArrayLiteral("ChangeOutputProperty"), |
|
QByteArrayLiteral("DeleteOutputProperty"), |
|
QByteArrayLiteral("GetOutputproperty"), |
|
QByteArrayLiteral("CreateMode"), |
|
QByteArrayLiteral("DestroyMode"), |
|
QByteArrayLiteral("AddOutputMode"), |
|
QByteArrayLiteral("DeleteOutputMode"), |
|
QByteArrayLiteral("GetCrtcInfo"), |
|
QByteArrayLiteral("SetCrtcConfig"), |
|
QByteArrayLiteral("GetCrtcGammaSize"), |
|
QByteArrayLiteral("GetCrtcGamma"), |
|
QByteArrayLiteral("SetCrtcGamma"), |
|
QByteArrayLiteral("GetScreenResourcesCurrent"), |
|
QByteArrayLiteral("SetCrtcTransform"), |
|
QByteArrayLiteral("GetCrtcTransform"), |
|
QByteArrayLiteral("GetPanning"), |
|
QByteArrayLiteral("SetPanning"), |
|
QByteArrayLiteral("SetOutputPrimary"), |
|
QByteArrayLiteral("GetOutputPrimary"), |
|
QByteArrayLiteral("GetProviders"), |
|
QByteArrayLiteral("GetProviderInfo"), |
|
QByteArrayLiteral("SetProviderOffloadSink"), |
|
QByteArrayLiteral("SetProviderOutputSource"), |
|
QByteArrayLiteral("ListProviderProperties"), |
|
QByteArrayLiteral("QueryProviderProperty"), |
|
QByteArrayLiteral("ConfigureProviderroperty"), |
|
QByteArrayLiteral("ChangeProviderProperty"), |
|
QByteArrayLiteral("DeleteProviderProperty"), |
|
QByteArrayLiteral("GetProviderProperty")}); |
|
} |
|
|
|
QVector<QByteArray> randrErrorCodes() |
|
{ |
|
// see https://www.x.org/releases/X11R7.7/doc/randrproto/randrproto.txt |
|
// extracted from <xcb/randr.h> |
|
return QVector<QByteArray>({QByteArrayLiteral("BadOutput"), |
|
QByteArrayLiteral("BadCrtc"), |
|
QByteArrayLiteral("BadMode"), |
|
QByteArrayLiteral("BadProvider")}); |
|
} |
|
|
|
QVector<QByteArray> damageOpCodes() |
|
{ |
|
// see https://www.x.org/releases/X11R7.7/doc/damageproto/damageproto.txt |
|
// extracted from <xcb/damage.h> |
|
return QVector<QByteArray>({QByteArrayLiteral("QueryVersion"), |
|
QByteArrayLiteral("Create"), |
|
QByteArrayLiteral("Destroy"), |
|
QByteArrayLiteral("Subtract"), |
|
QByteArrayLiteral("Add")}); |
|
} |
|
|
|
QVector<QByteArray> damageErrorCodes() |
|
{ |
|
// see https://www.x.org/releases/X11R7.7/doc/damageproto/damageproto.txt |
|
// extracted from <xcb/damage.h> |
|
return QVector<QByteArray>({QByteArrayLiteral("BadDamage")}); |
|
} |
|
|
|
QVector<QByteArray> compositeOpCodes() |
|
{ |
|
// see https://www.x.org/releases/X11R7.7/doc/compositeproto/compositeproto.txt |
|
// extracted from <xcb/composite.h> |
|
return QVector<QByteArray>({QByteArrayLiteral("QueryVersion"), |
|
QByteArrayLiteral("RedirectWindow"), |
|
QByteArrayLiteral("RedirectSubwindows"), |
|
QByteArrayLiteral("UnredirectWindow"), |
|
QByteArrayLiteral("UnredirectSubwindows"), |
|
QByteArrayLiteral("CreateRegionFromBorderClip"), |
|
QByteArrayLiteral("NameWindowPixmap"), |
|
QByteArrayLiteral("GetOverlayWindow"), |
|
QByteArrayLiteral("ReleaseOverlayWindow")}); |
|
} |
|
|
|
QVector<QByteArray> fixesOpCodes() |
|
{ |
|
// see https://www.x.org/releases/X11R7.7/doc/fixesproto/fixesproto.txt |
|
// extracted from <xcb/xfixes.h> |
|
return QVector<QByteArray>({QByteArrayLiteral("QueryVersion"), |
|
QByteArrayLiteral("ChangeSaveSet"), |
|
QByteArrayLiteral("SelectSelectionInput"), |
|
QByteArrayLiteral("SelectCursorInput"), |
|
QByteArrayLiteral("GetCursorImage"), |
|
QByteArrayLiteral("CreateRegion"), |
|
QByteArrayLiteral("CreateRegionFromBitmap"), |
|
QByteArrayLiteral("CreateRegionFromWindow"), |
|
QByteArrayLiteral("CreateRegionFromGc"), |
|
QByteArrayLiteral("CreateRegionFromPicture"), |
|
QByteArrayLiteral("DestroyRegion"), |
|
QByteArrayLiteral("SetRegion"), |
|
QByteArrayLiteral("CopyRegion"), |
|
QByteArrayLiteral("UnionRegion"), |
|
QByteArrayLiteral("IntersectRegion"), |
|
QByteArrayLiteral("SubtractRegion"), |
|
QByteArrayLiteral("InvertRegion"), |
|
QByteArrayLiteral("TranslateRegion"), |
|
QByteArrayLiteral("RegionExtents"), |
|
QByteArrayLiteral("FetchRegion"), |
|
QByteArrayLiteral("SetGcClipRegion"), |
|
QByteArrayLiteral("SetWindowShapeRegion"), |
|
QByteArrayLiteral("SetPictureClipRegion"), |
|
QByteArrayLiteral("SetCursorName"), |
|
QByteArrayLiteral("GetCursorName"), |
|
QByteArrayLiteral("GetCursorImageAndName"), |
|
QByteArrayLiteral("ChangeCursor"), |
|
QByteArrayLiteral("ChangeCursorByName"), |
|
QByteArrayLiteral("ExpandRegion"), |
|
QByteArrayLiteral("HideCursor"), |
|
QByteArrayLiteral("ShowCursor"), |
|
QByteArrayLiteral("CreatePointerBarrier"), |
|
QByteArrayLiteral("DeletePointerBarrier")}); |
|
} |
|
|
|
QVector<QByteArray> fixesErrorCodes() |
|
{ |
|
// see https://www.x.org/releases/X11R7.7/doc/fixesproto/fixesproto.txt |
|
// extracted from <xcb/xfixes.h> |
|
return QVector<QByteArray>({QByteArrayLiteral("BadRegion")}); |
|
} |
|
|
|
QVector<QByteArray> renderOpCodes() |
|
{ |
|
// see https://www.x.org/releases/X11R7.7/doc/renderproto/renderproto.txt |
|
// extracted from <xcb/render.h> |
|
return QVector<QByteArray>({QByteArrayLiteral("QueryVersion"), |
|
QByteArrayLiteral("QueryPictFormats"), |
|
QByteArrayLiteral("QueryPictIndexValues"), |
|
QByteArrayLiteral("CreatePicture"), |
|
QByteArrayLiteral("ChangePicture"), |
|
QByteArrayLiteral("SetPictureClipRectangles"), |
|
QByteArrayLiteral("FreePicture"), |
|
QByteArrayLiteral("Composite"), |
|
QByteArrayLiteral("Trapezoids"), |
|
QByteArrayLiteral("Triangles"), |
|
QByteArrayLiteral("TriStrip"), |
|
QByteArrayLiteral("TriFan"), |
|
QByteArrayLiteral("CreateGlyphSet"), |
|
QByteArrayLiteral("ReferenceGlyphSet"), |
|
QByteArrayLiteral("FreeGlyphSet"), |
|
QByteArrayLiteral("AddGlyphs"), |
|
QByteArrayLiteral("FreeGlyphs"), |
|
QByteArrayLiteral("CompositeGlyphs8"), |
|
QByteArrayLiteral("CompositeGlyphs16"), |
|
QByteArrayLiteral("CompositeGlyphs32"), |
|
QByteArrayLiteral("FillRectangles"), |
|
QByteArrayLiteral("CreateCursor"), |
|
QByteArrayLiteral("SetPictureTransform"), |
|
QByteArrayLiteral("QueryFilters"), |
|
QByteArrayLiteral("SetPictureFilter"), |
|
QByteArrayLiteral("CreateAnimCursor"), |
|
QByteArrayLiteral("AddTraps"), |
|
QByteArrayLiteral("CreateSolidFill"), |
|
QByteArrayLiteral("CreateLinearGradient"), |
|
QByteArrayLiteral("CreateRadialGradient"), |
|
QByteArrayLiteral("CreateConicalGradient")}); |
|
} |
|
|
|
QVector<QByteArray> syncOpCodes() |
|
{ |
|
// see https://www.x.org/releases/X11R7.7/doc/xextproto/sync.html |
|
// extracted from <xcb/sync.h> |
|
return QVector<QByteArray>({QByteArrayLiteral("Initialize"), |
|
QByteArrayLiteral("ListSystemCounters"), |
|
QByteArrayLiteral("CreateCounter"), |
|
QByteArrayLiteral("DestroyCounter"), |
|
QByteArrayLiteral("QueryCounter"), |
|
QByteArrayLiteral("Await"), |
|
QByteArrayLiteral("ChangeCounter"), |
|
QByteArrayLiteral("SetCounter"), |
|
QByteArrayLiteral("CreateAlarm"), |
|
QByteArrayLiteral("ChangeAlarm"), |
|
QByteArrayLiteral("DestroyAlarm"), |
|
QByteArrayLiteral("QueryAlarm"), |
|
QByteArrayLiteral("SetPriority"), |
|
QByteArrayLiteral("GetPriority"), |
|
QByteArrayLiteral("CreateFence"), |
|
QByteArrayLiteral("TriggerFence"), |
|
QByteArrayLiteral("ResetFence"), |
|
QByteArrayLiteral("DestroyFence"), |
|
QByteArrayLiteral("QueryFence"), |
|
QByteArrayLiteral("AwaitFence")}); |
|
} |
|
|
|
static QVector<QByteArray> glxOpCodes() |
|
{ |
|
return QVector<QByteArray>{ |
|
QByteArrayLiteral(""), |
|
QByteArrayLiteral("Render"), |
|
QByteArrayLiteral("RenderLarge"), |
|
QByteArrayLiteral("CreateContext"), |
|
QByteArrayLiteral("DestroyContext"), |
|
QByteArrayLiteral("MakeCurrent"), |
|
QByteArrayLiteral("IsDirect"), |
|
QByteArrayLiteral("QueryVersion"), |
|
QByteArrayLiteral("WaitGL"), |
|
QByteArrayLiteral("WaitX"), |
|
QByteArrayLiteral("CopyContext"), |
|
QByteArrayLiteral("SwapBuffers"), |
|
QByteArrayLiteral("UseXFont"), |
|
QByteArrayLiteral("CreateGLXPixmap"), |
|
QByteArrayLiteral("GetVisualConfigs"), |
|
QByteArrayLiteral("DestroyGLXPixmap"), |
|
QByteArrayLiteral("VendorPrivate"), |
|
QByteArrayLiteral("VendorPrivateWithReply"), |
|
QByteArrayLiteral("QueryExtensionsString"), |
|
QByteArrayLiteral("QueryServerString"), |
|
QByteArrayLiteral("ClientInfo"), |
|
QByteArrayLiteral("GetFBConfigs"), |
|
QByteArrayLiteral("CreatePixmap"), |
|
QByteArrayLiteral("DestroyPixmap"), |
|
QByteArrayLiteral("CreateNewContext"), |
|
QByteArrayLiteral("QueryContext"), |
|
QByteArrayLiteral("MakeContextCurrent"), |
|
QByteArrayLiteral("CreatePbuffer"), |
|
QByteArrayLiteral("DestroyPbuffer"), |
|
QByteArrayLiteral("GetDrawableAttributes"), |
|
QByteArrayLiteral("ChangeDrawableAttributes"), |
|
QByteArrayLiteral("CreateWindow"), |
|
QByteArrayLiteral("DeleteWindow"), |
|
QByteArrayLiteral("SetClientInfoARB"), |
|
QByteArrayLiteral("CreateContextAttribsARB"), |
|
QByteArrayLiteral("SetClientInfo2ARB") |
|
// Opcodes 36-100 are unused |
|
// The GL single commands begin at opcode 101 |
|
}; |
|
} |
|
|
|
static QVector<QByteArray> glxErrorCodes() |
|
{ |
|
return QVector<QByteArray>{ |
|
QByteArrayLiteral("BadContext"), |
|
QByteArrayLiteral("BadContextState"), |
|
QByteArrayLiteral("BadDrawable"), |
|
QByteArrayLiteral("BadPixmap"), |
|
QByteArrayLiteral("BadContextTag"), |
|
QByteArrayLiteral("BadCurrentWindow"), |
|
QByteArrayLiteral("BadRenderRequest"), |
|
QByteArrayLiteral("BadLargeRequest"), |
|
QByteArrayLiteral("UnsupportedPrivateRequest"), |
|
QByteArrayLiteral("BadFBConfig"), |
|
QByteArrayLiteral("BadPbuffer"), |
|
QByteArrayLiteral("BadCurrentDrawable"), |
|
QByteArrayLiteral("BadWindow"), |
|
QByteArrayLiteral("GLXBadProfileARB") |
|
}; |
|
} |
|
|
|
ExtensionData::ExtensionData() |
|
: version(0) |
|
, eventBase(0) |
|
, errorBase(0) |
|
, majorOpcode(0) |
|
, present(0) |
|
{ |
|
} |
|
|
|
template<typename reply, typename T, typename F> |
|
void Extensions::initVersion(T cookie, F f, ExtensionData *dataToFill) |
|
{ |
|
ScopedCPointer<reply> version(f(connection(), cookie, nullptr)); |
|
dataToFill->version = version->major_version * 0x10 + version->minor_version; |
|
} |
|
|
|
Extensions *Extensions::s_self = nullptr; |
|
|
|
Extensions *Extensions::self() |
|
{ |
|
if (!s_self) { |
|
s_self = new Extensions(); |
|
} |
|
return s_self; |
|
} |
|
|
|
void Extensions::destroy() |
|
{ |
|
delete s_self; |
|
s_self = nullptr; |
|
} |
|
|
|
Extensions::Extensions() |
|
{ |
|
init(); |
|
} |
|
|
|
Extensions::~Extensions() |
|
{ |
|
} |
|
|
|
void Extensions::init() |
|
{ |
|
xcb_connection_t *c = connection(); |
|
xcb_prefetch_extension_data(c, &xcb_shape_id); |
|
xcb_prefetch_extension_data(c, &xcb_randr_id); |
|
xcb_prefetch_extension_data(c, &xcb_damage_id); |
|
xcb_prefetch_extension_data(c, &xcb_composite_id); |
|
xcb_prefetch_extension_data(c, &xcb_xfixes_id); |
|
xcb_prefetch_extension_data(c, &xcb_render_id); |
|
xcb_prefetch_extension_data(c, &xcb_sync_id); |
|
xcb_prefetch_extension_data(c, &xcb_glx_id); |
|
|
|
m_shape.name = QByteArray("SHAPE"); |
|
m_randr.name = QByteArray("RANDR"); |
|
m_damage.name = QByteArray("DAMAGE"); |
|
m_composite.name = QByteArray("Composite"); |
|
m_fixes.name = QByteArray("XFIXES"); |
|
m_render.name = QByteArray("RENDER"); |
|
m_sync.name = QByteArray("SYNC"); |
|
m_glx.name = QByteArray("GLX"); |
|
|
|
m_shape.opCodes = shapeOpCodes(); |
|
m_randr.opCodes = randrOpCodes(); |
|
m_damage.opCodes = damageOpCodes(); |
|
m_composite.opCodes = compositeOpCodes(); |
|
m_fixes.opCodes = fixesOpCodes(); |
|
m_render.opCodes = renderOpCodes(); |
|
m_sync.opCodes = syncOpCodes(); |
|
m_glx.opCodes = glxOpCodes(); |
|
|
|
m_randr.errorCodes = randrErrorCodes(); |
|
m_damage.errorCodes = damageErrorCodes(); |
|
m_fixes.errorCodes = fixesErrorCodes(); |
|
m_glx.errorCodes = glxErrorCodes(); |
|
|
|
extensionQueryReply(xcb_get_extension_data(c, &xcb_shape_id), &m_shape); |
|
extensionQueryReply(xcb_get_extension_data(c, &xcb_randr_id), &m_randr); |
|
extensionQueryReply(xcb_get_extension_data(c, &xcb_damage_id), &m_damage); |
|
extensionQueryReply(xcb_get_extension_data(c, &xcb_composite_id), &m_composite); |
|
extensionQueryReply(xcb_get_extension_data(c, &xcb_xfixes_id), &m_fixes); |
|
extensionQueryReply(xcb_get_extension_data(c, &xcb_render_id), &m_render); |
|
extensionQueryReply(xcb_get_extension_data(c, &xcb_sync_id), &m_sync); |
|
extensionQueryReply(xcb_get_extension_data(c, &xcb_glx_id), &m_glx); |
|
|
|
// extension specific queries |
|
xcb_shape_query_version_cookie_t shapeVersion; |
|
xcb_randr_query_version_cookie_t randrVersion; |
|
xcb_damage_query_version_cookie_t damageVersion; |
|
xcb_composite_query_version_cookie_t compositeVersion; |
|
xcb_xfixes_query_version_cookie_t xfixesVersion; |
|
xcb_render_query_version_cookie_t renderVersion; |
|
xcb_sync_initialize_cookie_t syncVersion; |
|
if (m_shape.present) { |
|
shapeVersion = xcb_shape_query_version_unchecked(c); |
|
} |
|
if (m_randr.present) { |
|
randrVersion = xcb_randr_query_version_unchecked(c, RANDR_MAX_MAJOR, RANDR_MAX_MINOR); |
|
xcb_randr_select_input(connection(), rootWindow(), XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE); |
|
} |
|
if (m_damage.present) { |
|
damageVersion = xcb_damage_query_version_unchecked(c, DAMAGE_MAX_MAJOR, DAMAGE_MIN_MAJOR); |
|
} |
|
if (m_composite.present) { |
|
compositeVersion = xcb_composite_query_version_unchecked(c, COMPOSITE_MAX_MAJOR, COMPOSITE_MAX_MINOR); |
|
} |
|
if (m_fixes.present) { |
|
xfixesVersion = xcb_xfixes_query_version_unchecked(c, XFIXES_MAX_MAJOR, XFIXES_MAX_MINOR); |
|
} |
|
if (m_render.present) { |
|
renderVersion = xcb_render_query_version_unchecked(c, RENDER_MAX_MAJOR, RENDER_MAX_MINOR); |
|
} |
|
if (m_sync.present) { |
|
syncVersion = xcb_sync_initialize(c, SYNC_MAX_MAJOR, SYNC_MAX_MINOR); |
|
} |
|
// handle replies |
|
if (m_shape.present) { |
|
initVersion<xcb_shape_query_version_reply_t>(shapeVersion, &xcb_shape_query_version_reply, &m_shape); |
|
} |
|
if (m_randr.present) { |
|
initVersion<xcb_randr_query_version_reply_t>(randrVersion, &xcb_randr_query_version_reply, &m_randr); |
|
} |
|
if (m_damage.present) { |
|
initVersion<xcb_damage_query_version_reply_t>(damageVersion, &xcb_damage_query_version_reply, &m_damage); |
|
} |
|
if (m_composite.present) { |
|
initVersion<xcb_composite_query_version_reply_t>(compositeVersion, &xcb_composite_query_version_reply, &m_composite); |
|
} |
|
if (m_fixes.present) { |
|
initVersion<xcb_xfixes_query_version_reply_t>(xfixesVersion, &xcb_xfixes_query_version_reply, &m_fixes); |
|
} |
|
if (m_render.present) { |
|
initVersion<xcb_render_query_version_reply_t>(renderVersion, &xcb_render_query_version_reply, &m_render); |
|
} |
|
if (m_sync.present) { |
|
initVersion<xcb_sync_initialize_reply_t>(syncVersion, &xcb_sync_initialize_reply, &m_sync); |
|
} |
|
qCDebug(KWIN_CORE) << "Extensions: shape: 0x" << QString::number(m_shape.version, 16) |
|
<< " composite: 0x" << QString::number(m_composite.version, 16) |
|
<< " render: 0x" << QString::number(m_render.version, 16) |
|
<< " fixes: 0x" << QString::number(m_fixes.version, 16) |
|
<< " randr: 0x" << QString::number(m_randr.version, 16) |
|
<< " sync: 0x" << QString::number(m_sync.version, 16) |
|
<< " damage: 0x " << QString::number(m_damage.version, 16); |
|
} |
|
|
|
void Extensions::extensionQueryReply(const xcb_query_extension_reply_t *extension, ExtensionData *dataToFill) |
|
{ |
|
if (!extension) { |
|
return; |
|
} |
|
dataToFill->present = extension->present; |
|
dataToFill->eventBase = extension->first_event; |
|
dataToFill->errorBase = extension->first_error; |
|
dataToFill->majorOpcode = extension->major_opcode; |
|
} |
|
|
|
int Extensions::damageNotifyEvent() const |
|
{ |
|
return m_damage.eventBase + XCB_DAMAGE_NOTIFY; |
|
} |
|
|
|
bool Extensions::hasShape(xcb_window_t w) const |
|
{ |
|
if (!isShapeAvailable()) { |
|
return false; |
|
} |
|
ScopedCPointer<xcb_shape_query_extents_reply_t> extents(xcb_shape_query_extents_reply( |
|
connection(), xcb_shape_query_extents_unchecked(connection(), w), nullptr)); |
|
if (extents.isNull()) { |
|
return false; |
|
} |
|
return extents->bounding_shaped > 0; |
|
} |
|
|
|
bool Extensions::isCompositeOverlayAvailable() const |
|
{ |
|
return m_composite.version >= 0x03; // 0.3 |
|
} |
|
|
|
bool Extensions::isFixesRegionAvailable() const |
|
{ |
|
return m_fixes.version >= 0x30; // 3 |
|
} |
|
|
|
int Extensions::fixesCursorNotifyEvent() const |
|
{ |
|
return m_fixes.eventBase + XCB_XFIXES_CURSOR_NOTIFY; |
|
} |
|
|
|
bool Extensions::isShapeInputAvailable() const |
|
{ |
|
return m_shape.version >= 0x11; // 1.1 |
|
} |
|
|
|
int Extensions::randrNotifyEvent() const |
|
{ |
|
return m_randr.eventBase + XCB_RANDR_SCREEN_CHANGE_NOTIFY; |
|
} |
|
|
|
int Extensions::shapeNotifyEvent() const |
|
{ |
|
return m_shape.eventBase + XCB_SHAPE_NOTIFY; |
|
} |
|
|
|
int Extensions::syncAlarmNotifyEvent() const |
|
{ |
|
return m_sync.eventBase + XCB_SYNC_ALARM_NOTIFY; |
|
} |
|
|
|
QVector<ExtensionData> Extensions::extensions() const |
|
{ |
|
return { |
|
m_shape, |
|
m_randr, |
|
m_damage, |
|
m_composite, |
|
m_render, |
|
m_fixes, |
|
m_sync, |
|
m_glx |
|
}; |
|
} |
|
|
|
//**************************************** |
|
// Shm |
|
//**************************************** |
|
Shm::Shm() |
|
: m_shmId(-1) |
|
, m_buffer(nullptr) |
|
, m_segment(XCB_NONE) |
|
, m_valid(false) |
|
, m_pixmapFormat(XCB_IMAGE_FORMAT_XY_BITMAP) |
|
{ |
|
m_valid = init(); |
|
} |
|
|
|
Shm::~Shm() |
|
{ |
|
if (m_valid) { |
|
xcb_shm_detach(connection(), m_segment); |
|
shmdt(m_buffer); |
|
} |
|
} |
|
|
|
bool Shm::init() |
|
{ |
|
const xcb_query_extension_reply_t *ext = xcb_get_extension_data(connection(), &xcb_shm_id); |
|
if (!ext || !ext->present) { |
|
qCDebug(KWIN_CORE) << "SHM extension not available"; |
|
return false; |
|
} |
|
ScopedCPointer<xcb_shm_query_version_reply_t> version(xcb_shm_query_version_reply(connection(), |
|
xcb_shm_query_version_unchecked(connection()), nullptr)); |
|
if (version.isNull()) { |
|
qCDebug(KWIN_CORE) << "Failed to get SHM extension version information"; |
|
return false; |
|
} |
|
m_pixmapFormat = version->pixmap_format; |
|
const int MAXSIZE = 4096 * 2048 * 4; // TODO check there are not larger windows |
|
m_shmId = shmget(IPC_PRIVATE, MAXSIZE, IPC_CREAT | 0600); |
|
if (m_shmId < 0) { |
|
qCDebug(KWIN_CORE) << "Failed to allocate SHM segment"; |
|
return false; |
|
} |
|
m_buffer = shmat(m_shmId, nullptr, 0 /*read/write*/); |
|
if (-1 == reinterpret_cast<long>(m_buffer)) { |
|
qCDebug(KWIN_CORE) << "Failed to attach SHM segment"; |
|
shmctl(m_shmId, IPC_RMID, nullptr); |
|
return false; |
|
} |
|
shmctl(m_shmId, IPC_RMID, nullptr); |
|
|
|
m_segment = xcb_generate_id(connection()); |
|
const xcb_void_cookie_t cookie = xcb_shm_attach_checked(connection(), m_segment, m_shmId, false); |
|
ScopedCPointer<xcb_generic_error_t> error(xcb_request_check(connection(), cookie)); |
|
if (!error.isNull()) { |
|
qCDebug(KWIN_CORE) << "xcb_shm_attach error: " << error->error_code; |
|
shmdt(m_buffer); |
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
} // namespace Xcb |
|
} // namespace KWin
|
|
|