///////////////////////////////////////////////////////
| 1082 | |
| 1083 | //////////////////////////////////////////////////////////// |
| 1084 | void WindowImplX11::setIcon(Vector2u size, const std::uint8_t* pixels) |
| 1085 | { |
| 1086 | // X11 wants BGRA pixels: swap red and blue channels |
| 1087 | // Note: this memory will be freed by X11Ptr<XImage> deleter |
| 1088 | // NOLINTBEGIN(cppcoreguidelines-no-malloc) |
| 1089 | auto* iconPixels = static_cast<std::uint8_t*>(std::malloc(std::size_t{size.x} * std::size_t{size.y} * 4)); |
| 1090 | // NOLINTEND(cppcoreguidelines-no-malloc) |
| 1091 | for (std::size_t i = 0; i < std::size_t{size.x} * std::size_t{size.y}; ++i) |
| 1092 | { |
| 1093 | iconPixels[i * 4 + 0] = pixels[i * 4 + 2]; |
| 1094 | iconPixels[i * 4 + 1] = pixels[i * 4 + 1]; |
| 1095 | iconPixels[i * 4 + 2] = pixels[i * 4 + 0]; |
| 1096 | iconPixels[i * 4 + 3] = pixels[i * 4 + 3]; |
| 1097 | } |
| 1098 | |
| 1099 | // Create the icon pixmap |
| 1100 | Visual* defVisual = DefaultVisual(m_display.get(), m_screen); |
| 1101 | const auto defDepth = static_cast<unsigned int>(DefaultDepth(m_display.get(), m_screen)); |
| 1102 | const auto iconImage = X11Ptr<XImage>( |
| 1103 | XCreateImage(m_display.get(), defVisual, defDepth, ZPixmap, 0, reinterpret_cast<char*>(iconPixels), size.x, size.y, 32, 0)); |
| 1104 | if (!iconImage) |
| 1105 | { |
| 1106 | err() << "Failed to set the window's icon" << std::endl; |
| 1107 | return; |
| 1108 | } |
| 1109 | |
| 1110 | if (m_iconPixmap) |
| 1111 | XFreePixmap(m_display.get(), m_iconPixmap); |
| 1112 | |
| 1113 | if (m_iconMaskPixmap) |
| 1114 | XFreePixmap(m_display.get(), m_iconMaskPixmap); |
| 1115 | |
| 1116 | m_iconPixmap = XCreatePixmap(m_display.get(), RootWindow(m_display.get(), m_screen), size.x, size.y, defDepth); |
| 1117 | XGCValues values; |
| 1118 | GC iconGC = XCreateGC(m_display.get(), m_iconPixmap, 0, &values); |
| 1119 | XPutImage(m_display.get(), m_iconPixmap, iconGC, iconImage.get(), 0, 0, 0, 0, size.x, size.y); |
| 1120 | XFreeGC(m_display.get(), iconGC); |
| 1121 | |
| 1122 | // Create the mask pixmap (must have 1 bit depth) |
| 1123 | const std::size_t pitch = (size.x + 7) / 8; |
| 1124 | std::vector<std::uint8_t> maskPixels(pitch * size.y, 0); |
| 1125 | for (std::size_t j = 0; j < size.y; ++j) |
| 1126 | { |
| 1127 | for (std::size_t i = 0; i < pitch; ++i) |
| 1128 | { |
| 1129 | for (std::size_t k = 0; k < 8; ++k) |
| 1130 | { |
| 1131 | if (i * 8 + k < size.x) |
| 1132 | { |
| 1133 | const std::uint8_t opacity = pixels[(i * 8 + k + j * size.x) * 4 + 3] > 0; |
| 1134 | maskPixels[i + j * pitch] |= static_cast<std::uint8_t>(opacity << k); |
| 1135 | } |
| 1136 | } |
| 1137 | } |
| 1138 | } |
| 1139 | m_iconMaskPixmap = XCreatePixmapFromBitmapData(m_display.get(), |
| 1140 | m_window, |
| 1141 | reinterpret_cast<char*>(maskPixels.data()), |
nothing calls this directly
no test coverage detected