diff --git a/xbanan/Base.cpp b/xbanan/Base.cpp index 833b911..67fa1cf 100644 --- a/xbanan/Base.cpp +++ b/xbanan/Base.cpp @@ -2469,8 +2469,13 @@ BAN::ErrorOr handle_packet(Client& client_info, BAN::ConstByteSpan packet) dprintln(" gc {}", request.gc); dprintln(" mask {8h}", request.mask); + // TODO: support invisible background + uint32_t foreground = 0x000000; uint32_t background = 0x000000; + uint32_t clip_mask = 0; + int32_t clip_origin_x = 0; + int32_t clip_origin_y = 0; for (size_t i = 0; i < 32; i++) { if (!((request.mask >> i) & 1)) @@ -2487,6 +2492,18 @@ BAN::ErrorOr handle_packet(Client& client_info, BAN::ConstByteSpan packet) dprintln(" background: {8h}", value); background = value; break; + case 17: + dprintln(" clip-origin-x: {}", value); + clip_origin_x = value; + break; + case 18: + dprintln(" clip-origin-y: {}", value); + clip_origin_y = value; + break; + case 19: + dprintln(" clip-mask: {}", value); + clip_mask = value; + break; default: dprintln(" {8h}: {8h}", 1 << i, value); break; @@ -2499,6 +2516,9 @@ BAN::ErrorOr handle_packet(Client& client_info, BAN::ConstByteSpan packet) .object = Object::GraphicsContext { .foreground = foreground, .background = background, + .clip_mask = clip_mask, + .clip_origin_x = clip_origin_x, + .clip_origin_y = clip_origin_y, } })))); @@ -2509,14 +2529,16 @@ BAN::ErrorOr handle_packet(Client& client_info, BAN::ConstByteSpan packet) auto request = decode(packet).value(); dprintln("ChangeGC"); - dprintln(" gc {}", request.gc); - dprintln(" mask {8h}", request.mask); + dprintln(" gc: {}", request.gc); + dprintln(" mask: {8h}", request.mask); auto& object = *g_objects[request.gc]; ASSERT(object.type == Object::Type::GraphicsContext); auto& gc = object.object.get(); + // TODO: support invisible background + for (size_t i = 0; i < 32; i++) { if (!((request.mask >> i) & 1)) @@ -2533,6 +2555,19 @@ BAN::ErrorOr handle_packet(Client& client_info, BAN::ConstByteSpan packet) dprintln(" background: {8h}", value); gc.background = value; break; + case 17: + dprintln(" clip-origin-x: {}", value); + gc.clip_origin_x = value; + break; + case 18: + dprintln(" clip-origin-y: {}", value); + gc.clip_origin_y = value; + break; + case 19: + dprintln(" clip-mask: {}", value); + gc.clip_mask = value; + gc.clip_rects.clear(); + break; default: dprintln(" {8h}: {8h}", 1 << i, value); break; @@ -2541,6 +2576,34 @@ BAN::ErrorOr handle_packet(Client& client_info, BAN::ConstByteSpan packet) break; } + case X_SetClipRectangles: + { + auto request = decode(packet).value(); + + dprintln("SetClipRectangles"); + dprintln(" gc: {}", request.gc); + dprintln(" ordering: {}", request.ordering); + dprintln(" xOrigin: {}", request.xOrigin); + dprintln(" yOrigin: {}", request.yOrigin); + + auto& object = *g_objects[request.gc]; + ASSERT(object.type == Object::Type::GraphicsContext); + auto& gc = object.object.get(); + + auto rects = packet.as_span(); + + TRY(gc.clip_rects.resize(rects.size())); + gc.clip_mask = UINT32_MAX; + gc.clip_origin_x = request.xOrigin; + gc.clip_origin_y = request.yOrigin; + memcpy(gc.clip_rects.data(), rects.data(), rects.size() * sizeof(xRectangle)); + + dprintln(" rects:"); + for (auto rect : rects) + dprintln(" {},{} {},{}", rect.x, rect.y, rect.width, rect.height); + + break; + } case X_FreeGC: { const CARD32 gc = packet.as_span()[1]; @@ -2587,6 +2650,7 @@ BAN::ErrorOr handle_packet(Client& client_info, BAN::ConstByteSpan packet) dprintln("CopyArea"); dprintln(" srcDrawable: {}", request.srcDrawable); dprintln(" dstDrawable: {}", request.dstDrawable); + dprintln(" gc: {}", request.gc); dprintln(" srcX: {}", request.srcX); dprintln(" srcY: {}", request.srcY); dprintln(" dstX: {}", request.dstX); @@ -2600,6 +2664,10 @@ BAN::ErrorOr handle_packet(Client& client_info, BAN::ConstByteSpan packet) auto& dst_drawable = TRY_REF(get_drawable(request.dstDrawable)); auto [dst_data, dst_w, dst_h, dst_depth] = get_drawable_info(dst_drawable); + auto& gc_object = *g_objects[request.gc]; + ASSERT(gc_object.type == Object::Type::GraphicsContext); + auto& gc = gc_object.object.get(); + const auto get_pixel = [&](int32_t x, int32_t y) -> uint32_t { @@ -2673,7 +2741,8 @@ BAN::ErrorOr handle_packet(Client& client_info, BAN::ConstByteSpan packet) continue; if (dst_x < 0 || dst_x >= dst_w) continue; - set_pixel(dst_x, dst_y, get_pixel(src_x, src_y)); + if (!gc.is_clipped(dst_x, dst_y)) + set_pixel(dst_x, dst_y, get_pixel(src_x, src_y)); } } @@ -2692,6 +2761,7 @@ BAN::ErrorOr handle_packet(Client& client_info, BAN::ConstByteSpan packet) auto& gc_object = *g_objects[request.gc]; ASSERT(gc_object.type == Object::Type::GraphicsContext); + auto& gc = gc_object.object.get(); const auto foreground = gc_object.object.get().foreground; @@ -2715,7 +2785,8 @@ BAN::ErrorOr handle_packet(Client& client_info, BAN::ConstByteSpan packet) auto* data_u32 = data.as_span().data(); for (int32_t y = min_y; y < max_y; y++) for (int32_t x = min_x; x < max_x; x++) - data_u32[y * w + x] = foreground; + if (!gc.is_clipped(x, y)) + data_u32[y * w + x] = foreground; if (drawable.type == Object::Type::Window) invalidate_window(request.drawable, min_x, min_y, max_x - min_x, max_y - min_y); @@ -2733,6 +2804,7 @@ BAN::ErrorOr handle_packet(Client& client_info, BAN::ConstByteSpan packet) auto& gc_object = *g_objects[request.gc]; ASSERT(gc_object.type == Object::Type::GraphicsContext); + auto& gc = gc_object.object.get(); const auto foreground = gc_object.object.get().foreground; @@ -2805,7 +2877,8 @@ BAN::ErrorOr handle_packet(Client& client_info, BAN::ConstByteSpan packet) } } - texture.set_pixel(x, y, foreground); + if (gc.is_clipped(x, y)) + texture.set_pixel(x, y, foreground); } } @@ -2821,6 +2894,7 @@ BAN::ErrorOr handle_packet(Client& client_info, BAN::ConstByteSpan packet) #if 0 dprintln("PutImage"); dprintln(" drawable: {}", request.drawable); + dprintln(" gc: {}", request.gc); dprintln(" format: {}", request.format); dprintln(" depth: {}", request.depth); dprintln(" dstX: {}", request.dstX); @@ -2832,6 +2906,10 @@ BAN::ErrorOr handle_packet(Client& client_info, BAN::ConstByteSpan packet) auto& object = TRY_REF(get_drawable(request.drawable)); auto [out_data, out_w, out_h, out_depth] = get_drawable_info(object); + auto& gc_object = *g_objects[request.gc]; + ASSERT(gc_object.type == Object::Type::GraphicsContext); + auto& gc = gc_object.object.get(); + if (packet.empty()) { dwarnln("no data in PutImage"); @@ -2855,6 +2933,7 @@ BAN::ErrorOr handle_packet(Client& client_info, BAN::ConstByteSpan packet) .h = request.height, .left_pad = request.leftPad, .format = request.format, + .gc = gc, }); if (object.type == Object::Type::Window) diff --git a/xbanan/Definitions.h b/xbanan/Definitions.h index bab7674..0f9b07c 100644 --- a/xbanan/Definitions.h +++ b/xbanan/Definitions.h @@ -107,6 +107,30 @@ struct Object { uint32_t foreground; uint32_t background; + + uint32_t clip_mask; + int32_t clip_origin_x; + int32_t clip_origin_y; + BAN::Vector clip_rects; + + inline bool is_clipped(int32_t x, int32_t y) const + { + if (clip_mask == 0) + return false; + + if (clip_mask == UINT32_MAX) + { + x -= clip_origin_x; + y -= clip_origin_y; + for (const auto& rect : clip_rects) + if (x >= rect.x && y >= rect.y && x < rect.x + rect.width && y < rect.y + rect.height) + return false; + return true; + } + + // TODO pixmap clipping + return false; + } }; BAN::Variant object; diff --git a/xbanan/ExtSHM.cpp b/xbanan/ExtSHM.cpp index b6b5bc2..b13282c 100644 --- a/xbanan/ExtSHM.cpp +++ b/xbanan/ExtSHM.cpp @@ -222,6 +222,10 @@ static BAN::ErrorOr extension_shm(Client& client_info, BAN::ConstByteSpan auto& object = TRY_REF(get_drawable(request.drawable)); auto [out_data, out_w, out_h, out_depth] = get_drawable_info(object); + auto& gc_object = *g_objects[request.gc]; + ASSERT(gc_object.type == Object::Type::GraphicsContext); + auto& gc = gc_object.object.get(); + put_image({ .out_data = out_data.data(), .out_x = request.dstX, @@ -239,6 +243,7 @@ static BAN::ErrorOr extension_shm(Client& client_info, BAN::ConstByteSpan .h = request.srcHeight, .left_pad = 0, .format = request.format, + .gc = gc, }); if (object.type == Object::Type::Window) diff --git a/xbanan/Image.cpp b/xbanan/Image.cpp index c161d2f..0640c7d 100644 --- a/xbanan/Image.cpp +++ b/xbanan/Image.cpp @@ -52,7 +52,8 @@ void put_image(const PutImageInfo& info) for (size_t i = 0; i < info.in_depth; i++) if (in_data_u32[dword + i * dwords_per_plane] & bit_mask) pixel |= 1u << i; - out_data_u32[dst_off + x] = pixel; + if (!info.gc.is_clipped(x, y)) + out_data_u32[dst_off + x] = pixel; } } break; @@ -60,7 +61,7 @@ void put_image(const PutImageInfo& info) case ZPixmap: { ASSERT(info.left_pad == 0); - if (in_bpp == 32) + if (in_bpp == 32 && info.gc.clip_mask == None) { const auto bytes_per_row = (max_x - min_x) * 4; for (int32_t y = min_y; y < max_y; y++) @@ -82,7 +83,8 @@ void put_image(const PutImageInfo& info) const auto bit_offset = (info.in_y + y) * bits_per_scanline + (info.in_x + x) * in_bpp; const auto dword = bit_offset / 32; const auto shift = bit_offset % 32; - out_data_u32[dst_off + x] = (in_data_u32[dword] >> shift) & pixel_mask; + if (!info.gc.is_clipped(x, y)) + out_data_u32[dst_off + x] = (in_data_u32[dword] >> shift) & pixel_mask; } } } diff --git a/xbanan/Image.h b/xbanan/Image.h index a974556..8e7b6ae 100644 --- a/xbanan/Image.h +++ b/xbanan/Image.h @@ -1,7 +1,6 @@ #pragma once -#include -#include +#include "Definitions.h" struct PutImageInfo { @@ -24,6 +23,8 @@ struct PutImageInfo uint32_t left_pad; uint8_t format; + + const Object::GraphicsContext& gc; }; struct GetImageInfo