// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp #include #include #include #include #include #include #include namespace Nz { IconImpl::IconImpl() { ScopedXCBConnection connection; m_iconPixmap.Connect(connection); m_maskPixmap.Connect(connection); } bool IconImpl::Create(const Image& icon) { Image iconImage(icon); // Vive le COW if (!iconImage.Convert(Nz::PixelFormatType_BGRA8)) { NazaraError("Failed to convert icon to BGRA8"); return false; } auto width = iconImage.GetWidth(); auto height = iconImage.GetHeight(); ScopedXCBConnection connection; xcb_screen_t* screen = X11::XCBDefaultScreen(connection); if (!m_iconPixmap.Create( screen->root_depth, screen->root, width, height)) { NazaraError("Failed to create icon pixmap"); return false; } CallOnExit onExit([this](){ Destroy(); }); XCBGContext iconGC(connection); if (!iconGC.Create( m_iconPixmap, 0, nullptr)) { NazaraError("Failed to create icon gc"); return false; } if (!X11::CheckCookie( connection, xcb_put_image( connection, XCB_IMAGE_FORMAT_Z_PIXMAP, m_iconPixmap, iconGC, width, height, 0, 0, 0, screen->root_depth, width * height * 4, iconImage.GetConstPixels() ))) { NazaraError("Failed to put image for icon"); return false; } // Create the mask pixmap (must have 1 bit depth) std::size_t pitch = (width + 7) / 8; static std::vector maskPixels(pitch * height, 0); for (std::size_t j = 0; j < height; ++j) { for (std::size_t i = 0; i < pitch; ++i) { for (std::size_t k = 0; k < 8; ++k) { if (i * 8 + k < width) { UInt8 opacity = (iconImage.GetConstPixels()[(i * 8 + k + j * width) * 4 + 3] > 0) ? 1 : 0; maskPixels[i + j * pitch] |= (opacity << k); } } } } if (!m_maskPixmap.CreatePixmapFromBitmapData( X11::XCBDefaultRootWindow(connection), reinterpret_cast(&maskPixels[0]), width, height, 1, 0, 1, nullptr)) { NazaraError("Failed to create mask pixmap for icon"); return false; } onExit.Reset(); return true; } void IconImpl::Destroy() { m_iconPixmap.Destroy(); m_maskPixmap.Destroy(); } xcb_pixmap_t IconImpl::GetIcon() { return m_iconPixmap; } xcb_pixmap_t IconImpl::GetMask() { return m_maskPixmap; } }