File indexing completed on 2024-11-10 04:56:36

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2011 Arthur Arlt <a.arlt@stud.uni-heidelberg.de>
0006     SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 // own
0011 #include "x11_standalone_non_composited_outline.h"
0012 // KWin libs
0013 #include "../common/kwinxrenderutils.h"
0014 // xcb
0015 #include <xcb/render.h>
0016 
0017 namespace KWin
0018 {
0019 
0020 NonCompositedOutlineVisual::NonCompositedOutlineVisual(Outline *outline)
0021     : OutlineVisual(outline)
0022     , m_initialized(false)
0023 {
0024 }
0025 
0026 NonCompositedOutlineVisual::~NonCompositedOutlineVisual()
0027 {
0028 }
0029 
0030 void NonCompositedOutlineVisual::show()
0031 {
0032     if (!m_initialized) {
0033         const QRect geo(0, 0, 1, 1);
0034         const uint32_t values[] = {true};
0035         // TODO: use template variant
0036         m_leftOutline.create(geo, XCB_CW_OVERRIDE_REDIRECT, values);
0037         m_rightOutline.create(geo, XCB_CW_OVERRIDE_REDIRECT, values);
0038         m_topOutline.create(geo, XCB_CW_OVERRIDE_REDIRECT, values);
0039         m_bottomOutline.create(geo, XCB_CW_OVERRIDE_REDIRECT, values);
0040         m_initialized = true;
0041     }
0042 
0043     const int defaultDepth = Xcb::defaultDepth();
0044 
0045     const QRect &outlineGeometry = m_outline->geometry();
0046     // left/right parts are between top/bottom, they don't reach as far as the corners
0047     const uint16_t verticalWidth = 5;
0048     const uint16_t verticalHeight = outlineGeometry.height() - 10;
0049     const uint16_t horizontalWidth = outlineGeometry.width();
0050     const uint horizontalHeight = 5;
0051     m_leftOutline.setGeometry(outlineGeometry.x(), outlineGeometry.y() + 5, verticalWidth, verticalHeight);
0052     m_rightOutline.setGeometry(outlineGeometry.x() + outlineGeometry.width() - 5, outlineGeometry.y() + 5, verticalWidth, verticalHeight);
0053     m_topOutline.setGeometry(outlineGeometry.x(), outlineGeometry.y(), horizontalWidth, horizontalHeight);
0054     m_bottomOutline.setGeometry(outlineGeometry.x(), outlineGeometry.y() + outlineGeometry.height() - 5, horizontalWidth, horizontalHeight);
0055 
0056     const xcb_render_color_t white = {0xffff, 0xffff, 0xffff, 0xffff};
0057     QColor qGray(Qt::gray);
0058     const xcb_render_color_t gray = {
0059         uint16_t(0xffff * qGray.redF()),
0060         uint16_t(0xffff * qGray.greenF()),
0061         uint16_t(0xffff * qGray.blueF()),
0062         0xffff};
0063     const xcb_render_color_t black = {0, 0, 0, 0xffff};
0064     {
0065         xcb_pixmap_t xpix = xcb_generate_id(connection());
0066         xcb_create_pixmap(connection(), defaultDepth, xpix, rootWindow(), verticalWidth, verticalHeight);
0067         XRenderPicture pic(xpix, defaultDepth);
0068 
0069         xcb_rectangle_t rect = {0, 0, 5, verticalHeight};
0070         xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, white, 1, &rect);
0071         rect.x = 1;
0072         rect.width = 3;
0073         xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, gray, 1, &rect);
0074         rect.x = 2;
0075         rect.width = 1;
0076         xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, black, 1, &rect);
0077 
0078         m_leftOutline.setBackgroundPixmap(xpix);
0079         m_rightOutline.setBackgroundPixmap(xpix);
0080         // According to the XSetWindowBackgroundPixmap documentation the pixmap can be freed.
0081         xcb_free_pixmap(connection(), xpix);
0082     }
0083     {
0084         xcb_pixmap_t xpix = xcb_generate_id(connection());
0085         xcb_create_pixmap(connection(), defaultDepth, xpix, rootWindow(), horizontalWidth, horizontalHeight);
0086         XRenderPicture pic(xpix, defaultDepth);
0087 
0088         xcb_rectangle_t rect = {0, 0, horizontalWidth, horizontalHeight};
0089         xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, white, 1, &rect);
0090         xcb_rectangle_t grayRects[] = {
0091             {1, 1, uint16_t(horizontalWidth - 2), 3},
0092             {1, 4, 3, 1},
0093             {int16_t(horizontalWidth - 4), 4, 3, 1}};
0094         xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, gray, 3, grayRects);
0095         xcb_rectangle_t blackRects[] = {
0096             {2, 2, uint16_t(horizontalWidth - 4), 1},
0097             {2, 3, 1, 2},
0098             {int16_t(horizontalWidth - 3), 3, 1, 2}};
0099         xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, black, 3, blackRects);
0100         m_topOutline.setBackgroundPixmap(xpix);
0101         // According to the XSetWindowBackgroundPixmap documentation the pixmap can be freed.
0102         xcb_free_pixmap(connection(), xpix);
0103     }
0104     {
0105         xcb_pixmap_t xpix = xcb_generate_id(connection());
0106         xcb_create_pixmap(connection(), defaultDepth, xpix, rootWindow(), outlineGeometry.width(), 5);
0107         XRenderPicture pic(xpix, defaultDepth);
0108 
0109         xcb_rectangle_t rect = {0, 0, horizontalWidth, horizontalHeight};
0110         xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, white, 1, &rect);
0111         xcb_rectangle_t grayRects[] = {
0112             {1, 1, uint16_t(horizontalWidth - 2), 3},
0113             {1, 0, 3, 1},
0114             {int16_t(horizontalWidth - 4), 0, 3, 1}};
0115         xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, gray, 3, grayRects);
0116         xcb_rectangle_t blackRects[] = {
0117             {2, 2, uint16_t(horizontalWidth - 4), 1},
0118             {2, 0, 1, 2},
0119             {int16_t(horizontalWidth - 3), 0, 1, 2}};
0120         xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, pic, black, 3, blackRects);
0121         m_bottomOutline.setBackgroundPixmap(xpix);
0122         // According to the XSetWindowBackgroundPixmap documentation the pixmap can be freed.
0123         xcb_free_pixmap(connection(), xpix);
0124     }
0125     forEachWindow(&Xcb::Window::clear);
0126     forEachWindow(&Xcb::Window::map);
0127 }
0128 
0129 void NonCompositedOutlineVisual::hide()
0130 {
0131     forEachWindow(&Xcb::Window::unmap);
0132 }
0133 
0134 } // namespace