14#include <config-kwin.h>
16#include "compositor.h"
25#include <X11/extensions/XInput2.h>
31#include <drm_fourcc.h>
40 , m_buffer(graphicsBuffer)
48 m_buffer->disconnect(
this);
86 if (m_handle != XCB_CURSOR_NONE) {
88 m_handle = XCB_CURSOR_NONE;
97 xcb_pixmap_t pix = XCB_PIXMAP_NONE;
98 xcb_gcontext_t gc = XCB_NONE;
99 xcb_cursor_t cid = XCB_CURSOR_NONE;
101 if (!image.isNull()) {
107 const qreal outputScale = 1;
108 const QSize targetSize = image.size() * outputScale / image.devicePixelRatio();
109 const QImage img = image.scaled(targetSize, Qt::KeepAspectRatio).convertedTo(QImage::Format_ARGB32_Premultiplied);
111 xcb_create_pixmap(
connection, 32, pix, backend->
screen()->root, img.width(), img.height());
112 xcb_create_gc(
connection, gc, pix, 0,
nullptr);
114 xcb_put_image(
connection, XCB_IMAGE_FORMAT_Z_PIXMAP, pix, gc, img.width(), img.height(), 0, 0, 0, 32, img.sizeInBytes(), img.constBits());
117 xcb_render_create_cursor(
connection, cid, pic, qRound(hotspot.x() * outputScale), qRound(hotspot.y() * outputScale));
120 xcb_change_window_attributes(
connection, m_output->
window(), XCB_CW_CURSOR, &cid);
138 , m_renderLoop(std::make_unique<
RenderLoop>(this))
141 m_window = xcb_generate_id(m_backend->
connection());
143 static int identifier = -1;
146 .
name = QStringLiteral(
"X11-%1").arg(identifier),
154 xcb_present_select_input(m_backend->
connection(), m_presentEvent, m_window, 0);
155 xcb_unmap_window(m_backend->
connection(), m_window);
156 xcb_destroy_window(m_backend->
connection(), m_window);
162 return m_exposedArea;
167 m_exposedArea +=
rect;
172 m_exposedArea = QRegion();
177 return m_renderLoop.get();
187 return m_cursor.get();
197 return m_backend->
screen()->root_depth;
202 return m_hostPosition;
210 auto mode = std::make_shared<OutputMode>(
pixelSize, m_renderLoop->refreshRate());
213 initialState.
modes = {mode};
218 const uint32_t eventMask = XCB_EVENT_MASK_KEY_PRESS
219 | XCB_EVENT_MASK_KEY_RELEASE
220 | XCB_EVENT_MASK_BUTTON_PRESS
221 | XCB_EVENT_MASK_BUTTON_RELEASE
222 | XCB_EVENT_MASK_POINTER_MOTION
223 | XCB_EVENT_MASK_ENTER_WINDOW
224 | XCB_EVENT_MASK_LEAVE_WINDOW
225 | XCB_EVENT_MASK_STRUCTURE_NOTIFY
226 | XCB_EVENT_MASK_EXPOSURE;
228 const uint32_t values[] = {
229 m_backend->
screen()->black_pixel,
233 uint32_t valueMask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
236 XCB_COPY_FROM_PARENT,
238 m_backend->
screen()->root,
241 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT,
245 initXInputForWindow();
247 const uint32_t presentEventMask = XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY | XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY;
248 m_presentEvent = xcb_generate_id(m_backend->
connection());
249 xcb_present_select_input(m_backend->
connection(), m_presentEvent, m_window, presentEventMask);
251 m_winInfo = std::make_unique<NETWinInfo>(m_backend->
connection(), m_window, m_backend->
screen()->root,
252 NET::WMWindowType, NET::Properties2());
254 m_winInfo->setWindowType(NET::Normal);
255 m_winInfo->setPid(QCoreApplication::applicationPid());
256 QIcon windowIcon = QIcon::fromTheme(QStringLiteral(
"kwin"));
257 auto addIcon = [&windowIcon,
this](
const QSize &size) {
258 if (windowIcon.actualSize(size) != size) {
262 QImage windowImage = windowIcon.pixmap(size).toImage();
263 icon.data = windowImage.bits();
264 icon.size.width = size.width();
265 icon.size.height = size.height();
266 m_winInfo->setIcon(icon,
false);
268 addIcon(QSize(16, 16));
269 addIcon(QSize(32, 32));
270 addIcon(QSize(48, 48));
272 m_cursor = std::make_unique<X11WindowedCursor>(
this);
274 xcb_map_window(m_backend->
connection(), m_window);
277void X11WindowedOutput::initXInputForWindow()
283 XIEventMask evmasks[1];
284 unsigned char mask1[XIMaskLen(XI_LASTEVENT)];
286 memset(mask1, 0,
sizeof(mask1));
287 XISetMask(mask1, XI_TouchBegin);
288 XISetMask(mask1, XI_TouchUpdate);
289 XISetMask(mask1, XI_TouchOwnership);
290 XISetMask(mask1, XI_TouchEnd);
291 evmasks[0].deviceid = XIAllMasterDevices;
292 evmasks[0].mask_len =
sizeof(mask1);
293 evmasks[0].mask = mask1;
294 XISelectEvents(m_backend->
display(), m_window, evmasks, 1);
300 auto mode = std::make_shared<OutputMode>(
pixelSize, m_renderLoop->refreshRate());
310 std::chrono::microseconds timestamp(event->ust);
317 for (
auto &[graphicsBuffer, x11Buffer] : m_buffers) {
318 if (x11Buffer->pixmap() ==
event->pixmap) {
327 m_winInfo->setName(title.toUtf8().constData());
337 m_hostPosition = pos;
348 if (layer->isEnabled()) {
349 xcb_xfixes_show_cursor(m_backend->
connection(), m_window);
352 xcb_xfixes_hide_cursor(m_backend->
connection(), m_window);
364xcb_pixmap_t X11WindowedOutput::importDmaBufBuffer(
const DmaBufAttributes *attributes)
368 switch (attributes->
format) {
369 case DRM_FORMAT_ARGB8888:
373 case DRM_FORMAT_XRGB8888:
378 qCWarning(KWIN_X11WINDOWED) <<
"Cannot import a buffer with unsupported format";
379 return XCB_PIXMAP_NONE;
382 xcb_pixmap_t pixmap = xcb_generate_id(m_backend->
connection());
386 attributes->
fd[0].duplicate().take(),
387 attributes->
fd[1].duplicate().take(),
388 attributes->
fd[2].duplicate().take(),
389 attributes->
fd[3].duplicate().take(),
400 xcb_dri3_pixmap_from_buffer(m_backend->
connection(), pixmap, m_window,
402 attributes->
pitch[0],
depth, bpp, attributes->
fd[0].duplicate().take());
408xcb_pixmap_t X11WindowedOutput::importShmBuffer(
const ShmAttributes *attributes)
411 FileDescriptor poolFileDescriptor = attributes->fd.duplicate();
412 if (!poolFileDescriptor.isValid()) {
413 qCWarning(KWIN_X11WINDOWED) <<
"Failed to duplicate shm file descriptor";
414 return XCB_PIXMAP_NONE;
417 xcb_shm_seg_t segment = xcb_generate_id(m_backend->
connection());
418 xcb_shm_attach_fd(m_backend->
connection(), segment, poolFileDescriptor.take(), 0);
420 xcb_pixmap_t pixmap = xcb_generate_id(m_backend->
connection());
421 xcb_shm_create_pixmap(m_backend->
connection(), pixmap, m_window, attributes->size.width(), attributes->size.height(),
depth(), segment, 0);
422 xcb_shm_detach(m_backend->
connection(), segment);
429 std::unique_ptr<X11WindowedBuffer> &x11Buffer = m_buffers[graphicsBuffer];
431 xcb_pixmap_t pixmap = XCB_PIXMAP_NONE;
433 pixmap = importDmaBufBuffer(attributes);
435 pixmap = importShmBuffer(attributes);
437 if (pixmap == XCB_PIXMAP_NONE) {
438 return XCB_PIXMAP_NONE;
441 x11Buffer = std::make_unique<X11WindowedBuffer>(
this, pixmap, graphicsBuffer);
443 m_buffers.erase(graphicsBuffer);
448 return x11Buffer->pixmap();
458#include "moc_x11_windowed_output.cpp"
RenderBackend * backend() const
static Compositor * self()
virtual const DmaBufAttributes * dmabufAttributes() const
virtual const ShmAttributes * shmAttributes() const
uint32_t refreshRate() const
void setInformation(const Information &information)
void setState(const State &state)
virtual OutputLayer * cursorLayer(Output *output)
int driMajorVersion() const
xcb_connection_t * connection() const
int driMinorVersion() const
::Display * display() const
xcb_screen_t * screen() const
~X11WindowedBuffer() override
GraphicsBuffer * buffer() const
X11WindowedBuffer(X11WindowedOutput *output, xcb_pixmap_t pixmap, GraphicsBuffer *buffer)
xcb_pixmap_t pixmap() const
X11WindowedCursor(X11WindowedOutput *output)
void update(const QImage &image, const QPointF &hotspot)
~X11WindowedOutput() override
void resize(const QSize &pixelSize)
bool updateCursorLayer() override
xcb_pixmap_t importBuffer(GraphicsBuffer *buffer)
QPointF mapFromGlobal(const QPointF &pos) const
QRegion exposedArea() const
void handlePresentCompleteNotify(xcb_present_complete_notify_event_t *event)
QPoint hostPosition() const
void framePending(const std::shared_ptr< OutputFrame > &frame)
X11WindowedCursor * cursor() const
X11WindowedBackend * backend() const
void setHostPosition(const QPoint &pos)
RenderLoop * renderLoop() const override
xcb_window_t window() const
X11WindowedOutput(X11WindowedBackend *backend)
void handlePresentIdleNotify(xcb_present_idle_notify_event_t *event)
void addExposedArea(const QRect &rect)
QPoint internalPosition() const
void init(const QSize &pixelSize, qreal scale)
void setWindowTitle(const QString &title)
void updateEnabled(bool enabled)
Wrapper around XRender Picture.
KWIN_EXPORT xcb_connection_t * connection()
std::array< uint32_t, 4 > offset
std::array< uint32_t, 4 > pitch
std::array< FileDescriptor, 4 > fd
std::shared_ptr< OutputMode > currentMode
QList< std::shared_ptr< OutputMode > > modes