Add global safe getters for retrieving objects

This commit is contained in:
Oskari Alaranta 2026-02-21 14:36:45 +02:00
parent a52181e140
commit df32c7aa99
6 changed files with 237 additions and 403 deletions

View File

@ -3,6 +3,7 @@
#include "Font.h" #include "Font.h"
#include "Image.h" #include "Image.h"
#include "Keymap.h" #include "Keymap.h"
#include "SafeGetters.h"
#include "Utils.h" #include "Utils.h"
#include <X11/X.h> #include <X11/X.h>
@ -1085,78 +1086,8 @@ static void on_key_event(Client& client_info, WINDOW wid, LibGUI::EventPacket::K
BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet) BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
{ {
struct DrawableInfo
{
BAN::ByteSpan data;
CARD32 w, h;
CARD8 depth;
};
const uint8_t opcode = packet[0]; const uint8_t opcode = packet[0];
const auto get_window =
[&client_info, opcode](WINDOW wid) -> BAN::ErrorOr<Object::Window&>
{
auto it = g_objects.find(wid);
if (it == g_objects.end() || it->value->type != Object::Type::Window)
{
xError error {
.type = X_Error,
.errorCode = BadWindow,
.sequenceNumber = client_info.sequence,
.resourceID = wid,
.minorCode = 0,
.majorCode = opcode,
};
TRY(encode(client_info.output_buffer, error));
return BAN::Error::from_errno(ENOENT);
}
return it->value->object.get<Object::Window>();
};
const auto get_pixmap =
[&client_info, opcode](WINDOW wid) -> BAN::ErrorOr<Object::Pixmap&>
{
auto it = g_objects.find(wid);
if (it == g_objects.end() || it->value->type != Object::Type::Pixmap)
{
xError error {
.type = X_Error,
.errorCode = BadPixmap,
.sequenceNumber = client_info.sequence,
.resourceID = wid,
.minorCode = 0,
.majorCode = opcode,
};
TRY(encode(client_info.output_buffer, error));
return BAN::Error::from_errno(ENOENT);
}
return it->value->object.get<Object::Pixmap>();
};
const auto get_drawable =
[&client_info, opcode](WINDOW drawable) -> BAN::ErrorOr<Object&>
{
auto it = g_objects.find(drawable);
if (it == g_objects.end() || (it->value->type != Object::Type::Window && it->value->type != Object::Type::Pixmap))
{
xError error {
.type = X_Error,
.errorCode = BadDrawable,
.sequenceNumber = client_info.sequence,
.resourceID = drawable,
.minorCode = 0,
.majorCode = opcode,
};
TRY(encode(client_info.output_buffer, error));
return BAN::Error::from_errno(ENOENT);
}
return *it->value;
};
const auto validate_atom = const auto validate_atom =
[&client_info, opcode](ATOM atom) -> BAN::ErrorOr<void> [&client_info, opcode](ATOM atom) -> BAN::ErrorOr<void>
{ {
@ -1186,43 +1117,6 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
return it->value.sv(); return it->value.sv();
}; };
const auto get_drawable_info =
[](Object& object) -> DrawableInfo
{
DrawableInfo info;
switch (object.type)
{
case Object::Type::Window:
{
auto& window = object.object.get<Object::Window>();
auto& texture = window.texture();
info.data = { reinterpret_cast<uint8_t*>(texture.pixels().data()), texture.pixels().size() * 4 };
info.w = texture.width();
info.h = texture.height();
info.depth = window.depth;
break;
}
case Object::Type::Pixmap:
{
auto& pixmap = object.object.get<Object::Pixmap>();
info.data = pixmap.data;
info.w = pixmap.width;
info.h = pixmap.height;
info.depth = pixmap.depth;
break;
}
default:
ASSERT_NOT_REACHED();
}
return info;
};
client_info.sequence++; client_info.sequence++;
if (opcode >= 128) if (opcode >= 128)
@ -1408,7 +1302,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln(" window: {}", request.window); dprintln(" window: {}", request.window);
dprintln(" valueMask: {8h}", request.valueMask); dprintln(" valueMask: {8h}", request.valueMask);
auto& window = TRY_REF(get_window(request.window)); auto& window = TRY_REF(get_window(client_info, request.window, opcode));
CURSOR cursor_id = None; CURSOR cursor_id = None;
@ -1469,7 +1363,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln("GetWindowAttributes"); dprintln("GetWindowAttributes");
dprintln(" window: {}", wid); dprintln(" window: {}", wid);
const auto& window = TRY_REF(get_window(wid)); const auto& window = TRY_REF(get_window(client_info, wid, opcode));
xGetWindowAttributesReply reply { xGetWindowAttributesReply reply {
.type = X_Reply, .type = X_Reply,
@ -1502,7 +1396,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln("DestroyWinow"); dprintln("DestroyWinow");
dprintln(" window: {}", wid); dprintln(" window: {}", wid);
(void)TRY_REF(get_window(wid)); (void)TRY_REF(get_window(client_info, wid, opcode));
TRY(destroy_window(client_info, wid)); TRY(destroy_window(client_info, wid));
break; break;
@ -1517,9 +1411,9 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln(" x: {}", request.x); dprintln(" x: {}", request.x);
dprintln(" y: {}", request.y); dprintln(" y: {}", request.y);
auto& window = TRY_REF(get_window(request.window)); auto& window = TRY_REF(get_window(client_info, request.window, opcode));
auto& new_parent = TRY_REF(get_window(request.parent)); auto& new_parent = TRY_REF(get_window(client_info, request.parent, opcode));
auto& old_parent = TRY_REF(get_window(window.parent)); auto& old_parent = TRY_REF(get_window(client_info, window.parent, opcode));
const auto wid = request.window; const auto wid = request.window;
const auto oldpwid = window.parent; const auto oldpwid = window.parent;
@ -1589,7 +1483,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln("MapWindow"); dprintln("MapWindow");
dprintln(" window: {}", wid); dprintln(" window: {}", wid);
(void)TRY_REF(get_window(wid)); (void)TRY_REF(get_window(client_info, wid, opcode));
TRY(map_window(client_info, wid)); TRY(map_window(client_info, wid));
break; break;
@ -1601,7 +1495,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln("MapSubwindows"); dprintln("MapSubwindows");
dprintln(" window: {}", wid); dprintln(" window: {}", wid);
const auto& window = TRY_REF(get_window(wid)); const auto& window = TRY_REF(get_window(client_info, wid, opcode));
for (auto child_wid : window.children) for (auto child_wid : window.children)
TRY(map_window(client_info, child_wid)); TRY(map_window(client_info, child_wid));
@ -1614,7 +1508,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln("UnmapWindow"); dprintln("UnmapWindow");
dprintln(" window: {}", wid); dprintln(" window: {}", wid);
(void)TRY_REF(get_window(wid)); (void)TRY_REF(get_window(client_info, wid, opcode));
TRY(unmap_window(client_info, wid)); TRY(unmap_window(client_info, wid));
break; break;
@ -1626,7 +1520,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln("UnmapSubwindows"); dprintln("UnmapSubwindows");
dprintln(" window: {}", wid); dprintln(" window: {}", wid);
const auto& window = TRY_REF(get_window(wid)); const auto& window = TRY_REF(get_window(client_info, wid, opcode));
for (auto child_wid : window.children) for (auto child_wid : window.children)
TRY(unmap_window(client_info, child_wid)); TRY(unmap_window(client_info, child_wid));
@ -1639,7 +1533,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln("ConfigureWindow"); dprintln("ConfigureWindow");
dprintln(" window: {}", request.window); dprintln(" window: {}", request.window);
auto& window = TRY_REF(get_window(request.window)); auto& window = TRY_REF(get_window(client_info, request.window, opcode));
auto& texture = window.texture(); auto& texture = window.texture();
int32_t new_x = window.x; int32_t new_x = window.x;
@ -1764,7 +1658,22 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln("GetGeometry"); dprintln("GetGeometry");
dprintln(" drawable: {}", drawable_id); dprintln(" drawable: {}", drawable_id);
const auto& drawable = TRY_REF(get_drawable(drawable_id)); auto it = g_objects.find(drawable_id);
if (it == g_objects.end() || (it->value->type != Object::Type::Window && it->value->type != Object::Type::Pixmap))
{
xError error {
.type = X_Error,
.errorCode = BadDrawable,
.sequenceNumber = client_info.sequence,
.resourceID = drawable_id,
.minorCode = 0,
.majorCode = opcode,
};
TRY(encode(client_info.output_buffer, error));
return {};
}
const auto& drawable = *it->value;
INT16 x, y; INT16 x, y;
CARD16 width, height; CARD16 width, height;
@ -1824,7 +1733,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln("QueryTree"); dprintln("QueryTree");
dprintln(" window: {}", wid); dprintln(" window: {}", wid);
const auto& window = TRY_REF(get_window(wid)); const auto& window = TRY_REF(get_window(client_info, wid, opcode));
xQueryTreeReply reply { xQueryTreeReply reply {
.type = X_Reply, .type = X_Reply,
@ -1914,7 +1823,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
ASSERT(request.format == 8 || request.format == 16 || request.format == 32); ASSERT(request.format == 8 || request.format == 16 || request.format == 32);
auto& window = TRY_REF(get_window(request.window)); auto& window = TRY_REF(get_window(client_info, request.window, opcode));
auto it = window.properties.find(request.property); auto it = window.properties.find(request.property);
if (it == window.properties.end()) if (it == window.properties.end())
@ -1978,7 +1887,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln(" window: {}", request.window); dprintln(" window: {}", request.window);
dprintln(" property: {}", g_atoms_id_to_name[request.property]); dprintln(" property: {}", g_atoms_id_to_name[request.property]);
auto& window = TRY_REF(get_window(request.window)); auto& window = TRY_REF(get_window(client_info, request.window, opcode));
auto it = window.properties.find(request.property); auto it = window.properties.find(request.property);
if (it == window.properties.end()) if (it == window.properties.end())
@ -2015,7 +1924,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln(" longOffset: {}", request.longOffset); dprintln(" longOffset: {}", request.longOffset);
dprintln(" longLength: {}", request.longLength); dprintln(" longLength: {}", request.longLength);
auto& window = TRY_REF(get_window(request.window)); auto& window = TRY_REF(get_window(client_info, request.window, opcode));
auto it = window.properties.find(request.property); auto it = window.properties.find(request.property);
if (it == window.properties.end()) if (it == window.properties.end())
@ -2098,7 +2007,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln("ListProperties"); dprintln("ListProperties");
dprintln(" window: {}", wid); dprintln(" window: {}", wid);
const auto& window = TRY_REF(get_window(wid)); const auto& window = TRY_REF(get_window(client_info, wid, opcode));
xListPropertiesReply reply { xListPropertiesReply reply {
.type = X_Reply, .type = X_Reply,
@ -2348,7 +2257,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln("QueryPointer"); dprintln("QueryPointer");
dprintln(" window: {}", wid); dprintln(" window: {}", wid);
const auto& window = TRY_REF(get_window(wid)); const auto& window = TRY_REF(get_window(client_info, wid, opcode));
int32_t root_x, root_y; int32_t root_x, root_y;
int32_t event_x, event_y; int32_t event_x, event_y;
@ -2482,7 +2391,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln("FreePixmap"); dprintln("FreePixmap");
dprintln(" pixmap: {}", pid); dprintln(" pixmap: {}", pid);
(void)TRY_REF(get_pixmap(pid)); (void)TRY_REF(get_pixmap(client_info, pid, opcode));
client_info.objects.remove(pid); client_info.objects.remove(pid);
g_objects.remove(pid); g_objects.remove(pid);
@ -2659,6 +2568,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln("FreeGC"); dprintln("FreeGC");
dprintln(" gc: {}", gc); dprintln(" gc: {}", gc);
(void)TRY_REF(get_gc(client_info, gc, opcode));
client_info.objects.remove(gc); client_info.objects.remove(gc);
g_objects.remove(gc); g_objects.remove(gc);
@ -2676,10 +2586,8 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln(" width: {}", request.width); dprintln(" width: {}", request.width);
dprintln(" height: {}", request.height); dprintln(" height: {}", request.height);
auto& object = *g_objects[request.window]; auto& window = TRY_REF(get_window(client_info, request.window, opcode));
ASSERT(object.type == Object::Type::Window); auto& texture = window.texture();
auto& texture = object.object.get<Object::Window>().texture();
if (request.width == 0) if (request.width == 0)
request.width = texture.width() - request.x; request.width = texture.width() - request.x;
@ -2706,71 +2614,21 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln(" width: {}", request.width); dprintln(" width: {}", request.width);
dprintln(" heigth: {}", request.height); dprintln(" heigth: {}", request.height);
auto& src_drawable = TRY_REF(get_drawable(request.srcDrawable)); auto [src_data_u32, src_w, src_h, _] = TRY(get_drawable_info(client_info, request.srcDrawable, opcode));
auto [src_data, src_w, src_h, src_depth] = get_drawable_info(src_drawable); auto [dst_data_u32, dst_w, dst_h, _] = TRY(get_drawable_info(client_info, request.dstDrawable, opcode));
auto& dst_drawable = TRY_REF(get_drawable(request.dstDrawable)); const auto& gc = TRY_REF(get_gc(client_info, request.gc, opcode));
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<Object::GraphicsContext>();
const auto get_pixel = const auto get_pixel =
[&](int32_t x, int32_t y) -> uint32_t [src_data_u32, src_w](int32_t x, int32_t y) -> uint32_t
{ {
const int32_t index = y * src_w + x; return src_data_u32[y * src_w + x];
const auto src_data_u32 = src_data.as_span<uint32_t>();
return src_data_u32[index];
switch (src_depth)
{
case 1:
{
const int32_t byte = index / 8;
const int32_t bit = index % 8;
return (src_data[byte] & (1 << bit)) ? 0xFFFFFF : 0x000000;
}
case 24:
case 32:
{
const auto src_data_u32 = src_data.as_span<uint32_t>();
return src_data_u32[index];
}
default:
ASSERT_NOT_REACHED();
}
}; };
const auto set_pixel = const auto set_pixel =
[&](int32_t x, int32_t y, uint32_t color) -> void [dst_data_u32, dst_w](int32_t x, int32_t y, uint32_t color) -> void
{ {
const int32_t index = y * dst_w + x; dst_data_u32[y * dst_w + x] = color;
const auto dst_data_u32 = dst_data.as_span<uint32_t>();
dst_data_u32[index] = color;
switch (dst_depth)
{
case 1:
{
const int32_t byte = index / 8;
const int32_t bit = index % 8;
if (color)
dst_data[byte] |= (1 << bit);
else
dst_data[byte] &= ~(1 << bit);
break;
}
case 24:
case 32:
{
const auto dst_data_u32 = dst_data.as_span<uint32_t>();
dst_data_u32[index] = color;
break;
}
default:
ASSERT_NOT_REACHED();
}
}; };
const int32_t start_x = request.srcX < request.dstX ? request.width - 1 : 0; const int32_t start_x = request.srcX < request.dstX ? request.width - 1 : 0;
@ -2816,7 +2674,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
TRY(encode(client_info.output_buffer, event)); TRY(encode(client_info.output_buffer, event));
} }
if (dst_drawable.type == Object::Type::Window) if (g_objects[request.dstDrawable]->type == Object::Type::Window)
invalidate_window(request.dstDrawable, request.dstX, request.dstY, request.width, request.height); invalidate_window(request.dstDrawable, request.dstX, request.dstY, request.width, request.height);
break; break;
@ -2829,14 +2687,10 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln(" drawable: {}", request.drawable); dprintln(" drawable: {}", request.drawable);
dprintln(" gc: {}", request.gc); dprintln(" gc: {}", request.gc);
auto& gc_object = *g_objects[request.gc]; auto [out_data_u32, out_w, out_h, _] = TRY(get_drawable_info(client_info, request.drawable, opcode));
ASSERT(gc_object.type == Object::Type::GraphicsContext);
auto& gc = gc_object.object.get<Object::GraphicsContext>();
const auto foreground = gc_object.object.get<Object::GraphicsContext>().foreground; const auto& gc = TRY_REF(get_gc(client_info, request.gc, opcode));
const auto foreground = gc.foreground;
auto& drawable = TRY_REF(get_drawable(request.drawable));
auto [data, w, h, depth] = get_drawable_info(drawable);
dprintln(" rects:"); dprintln(" rects:");
while (!packet.empty()) while (!packet.empty())
@ -2849,16 +2703,15 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
const int32_t min_x = BAN::Math::max<int32_t>(rect.x, 0); const int32_t min_x = BAN::Math::max<int32_t>(rect.x, 0);
const int32_t min_y = BAN::Math::max<int32_t>(rect.y, 0); const int32_t min_y = BAN::Math::max<int32_t>(rect.y, 0);
const int32_t max_x = BAN::Math::min<int32_t>(rect.x + rect.width, w); const int32_t max_x = BAN::Math::min<int32_t>(rect.x + rect.width, out_w);
const int32_t max_y = BAN::Math::min<int32_t>(rect.y + rect.height, h); const int32_t max_y = BAN::Math::min<int32_t>(rect.y + rect.height, out_h);
auto* data_u32 = data.as_span<uint32_t>().data();
for (int32_t y = min_y; y < max_y; y++) for (int32_t y = min_y; y < max_y; y++)
for (int32_t x = min_x; x < max_x; x++) for (int32_t x = min_x; x < max_x; x++)
if (!gc.is_clipped(x, y)) if (!gc.is_clipped(x, y))
data_u32[y * w + x] = foreground; out_data_u32[y * out_w + x] = foreground;
if (drawable.type == Object::Type::Window) if (g_objects[request.drawable]->type == Object::Type::Window)
invalidate_window(request.drawable, min_x, min_y, max_x - min_x, max_y - min_y); invalidate_window(request.drawable, min_x, min_y, max_x - min_x, max_y - min_y);
} }
@ -2872,16 +2725,10 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln(" drawable: {}", request.drawable); dprintln(" drawable: {}", request.drawable);
dprintln(" gc: {}", request.gc); dprintln(" gc: {}", request.gc);
auto& gc_object = *g_objects[request.gc]; auto [out_data_32, out_w, out_h, _] = TRY(get_drawable_info(client_info, request.drawable, opcode));
ASSERT(gc_object.type == Object::Type::GraphicsContext);
auto& gc = gc_object.object.get<Object::GraphicsContext>();
const auto foreground = gc_object.object.get<Object::GraphicsContext>().foreground; auto& gc = TRY_REF(get_gc(client_info, request.gc, X_PolyFillArc));
const auto foreground = gc.foreground;
auto& object = *g_objects[request.drawable];
ASSERT(object.type == Object::Type::Window);
auto& texture = object.object.get<Object::Window>().texture();
const auto normalize_angle = const auto normalize_angle =
[](float f) -> float [](float f) -> float
@ -2906,8 +2753,8 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
const int32_t min_x = BAN::Math::max<int32_t>(0, arc.x); const int32_t min_x = BAN::Math::max<int32_t>(0, arc.x);
const int32_t min_y = BAN::Math::max<int32_t>(0, arc.y); const int32_t min_y = BAN::Math::max<int32_t>(0, arc.y);
const int32_t max_x = BAN::Math::min<int32_t>(texture.width(), arc.x + arc.width); const int32_t max_x = BAN::Math::min<int32_t>(out_w, arc.x + arc.width);
const int32_t max_y = BAN::Math::min<int32_t>(texture.height(), arc.y + arc.height); const int32_t max_y = BAN::Math::min<int32_t>(out_h, arc.y + arc.height);
const auto rx = arc.width / 2; const auto rx = arc.width / 2;
const auto ry = arc.height / 2; const auto ry = arc.height / 2;
@ -2947,11 +2794,12 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
} }
} }
if (gc.is_clipped(x, y)) if (!gc.is_clipped(x, y))
texture.set_pixel(x, y, foreground); out_data_32[y * out_w + x] = foreground;
} }
} }
if (g_objects[request.drawable]->type == Object::Type::Window)
invalidate_window(request.drawable, min_x, min_y, max_x - min_x, max_y - min_y); invalidate_window(request.drawable, min_x, min_y, max_x - min_x, max_y - min_y);
} }
@ -2973,12 +2821,10 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln(" height: {}", request.height); dprintln(" height: {}", request.height);
#endif #endif
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]; auto [out_data, out_w, out_h, out_depth] = TRY(get_drawable_info(client_info, request.drawable, opcode));
ASSERT(gc_object.type == Object::Type::GraphicsContext);
auto& gc = gc_object.object.get<Object::GraphicsContext>(); const auto& gc = TRY_REF(get_gc(client_info, request.gc, opcode));
if (packet.empty()) if (packet.empty())
{ {
@ -2987,7 +2833,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
} }
put_image({ put_image({
.out_data = out_data.data(), .out_data = out_data,
.out_x = request.dstX, .out_x = request.dstX,
.out_y = request.dstY, .out_y = request.dstY,
.out_w = out_w, .out_w = out_w,
@ -3006,7 +2852,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
.gc = gc, .gc = gc,
}); });
if (object.type == Object::Type::Window) if (g_objects[request.drawable]->type == Object::Type::Window)
invalidate_window(request.drawable, request.dstX, request.dstY, request.width, request.height); invalidate_window(request.drawable, request.dstX, request.dstY, request.width, request.height);
break; break;
@ -3024,8 +2870,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln(" height: {}", request.height); dprintln(" height: {}", request.height);
dprintln(" planeMask: {}", request.planeMask); dprintln(" planeMask: {}", request.planeMask);
auto& object = *g_objects[request.drawable]; auto [in_data, in_w, in_h, in_depth] = TRY(get_drawable_info(client_info, request.drawable, opcode));
auto [in_data, in_w, in_h, in_depth] = get_drawable_info(object);
const auto dwords = image_dwords(request.width, request.height, in_depth); const auto dwords = image_dwords(request.width, request.height, in_depth);
@ -3045,7 +2890,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
get_image({ get_image({
.out_data = out_data, .out_data = out_data,
.in_data = in_data.data(), .in_data = in_data,
.in_x = request.x, .in_x = request.x,
.in_y = request.y, .in_y = request.y,
.in_w = in_w, .in_w = in_w,
@ -3200,7 +3045,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
dprintln(" x: {}", request.x); dprintln(" x: {}", request.x);
dprintln(" y: {}", request.y); dprintln(" y: {}", request.y);
const auto& source = TRY_REF(get_pixmap(request.source)); const auto& source = TRY_REF(get_pixmap(client_info, request.source, opcode));
ASSERT(source.depth == 1); ASSERT(source.depth == 1);
const uint32_t foreground = const uint32_t foreground =
@ -3226,7 +3071,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
if (request.mask != None) if (request.mask != None)
{ {
const auto& mask = TRY_REF(get_pixmap(request.mask)); const auto& mask = TRY_REF(get_pixmap(client_info, request.mask, opcode));
ASSERT(mask.depth == 1); ASSERT(mask.depth == 1);
ASSERT(mask.width == source.width); ASSERT(mask.width == source.width);
ASSERT(mask.height == source.height); ASSERT(mask.height == source.height);

View File

@ -8,6 +8,7 @@ set(SOURCES
Font.cpp Font.cpp
Image.cpp Image.cpp
Keymap.cpp Keymap.cpp
SafeGetters.cpp
) )
include(CheckSymbolExists) include(CheckSymbolExists)

View File

@ -1,6 +1,7 @@
#include "Base.h" #include "Base.h"
#include "Extensions.h" #include "Extensions.h"
#include "Image.h" #include "Image.h"
#include "SafeGetters.h"
#include "Utils.h" #include "Utils.h"
#include <X11/X.h> #include <X11/X.h>
@ -42,21 +43,8 @@ static bool is_local_socket(int socket)
return false; return false;
} }
static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan packet) static BAN::ErrorOr<void*> get_shmseg(Client& client_info, CARD32 shmseg, BYTE op_major, BYTE op_minor)
{ {
struct DrawableInfo
{
BAN::ByteSpan data;
CARD32 w, h;
CARD8 depth;
};
const uint8_t major_opcode = packet[0];
const uint8_t minor_opcode = packet[1];
const auto get_shmseg =
[&client_info, minor_opcode, major_opcode](CARD32 shmseg) -> BAN::ErrorOr<void*>
{
auto it = g_objects.find(shmseg); auto it = g_objects.find(shmseg);
if (it != g_objects.end() && it->value->type == Object::Type::Extension) if (it != g_objects.end() && it->value->type == Object::Type::Extension)
{ {
@ -70,72 +58,19 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
.errorCode = static_cast<BYTE>(s_shm_error_base + BadShmSeg), .errorCode = static_cast<BYTE>(s_shm_error_base + BadShmSeg),
.sequenceNumber = client_info.sequence, .sequenceNumber = client_info.sequence,
.resourceID = shmseg, .resourceID = shmseg,
.minorCode = minor_opcode, .minorCode = op_minor,
.majorCode = major_opcode, .majorCode = op_major,
}; };
TRY(encode(client_info.output_buffer, error)); TRY(encode(client_info.output_buffer, error));
return BAN::Error::from_errno(ENOENT); return BAN::Error::from_errno(ENOENT);
}; }
const auto get_drawable = static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan packet)
[&client_info, minor_opcode, major_opcode](WINDOW drawable) -> BAN::ErrorOr<Object&> {
{ const uint8_t op_major = packet[0];
auto it = g_objects.find(drawable); const uint8_t op_minor = packet[1];
if (it == g_objects.end() || (it->value->type != Object::Type::Window && it->value->type != Object::Type::Pixmap))
{
xError error {
.type = X_Error,
.errorCode = BadDrawable,
.sequenceNumber = client_info.sequence,
.resourceID = drawable,
.minorCode = minor_opcode,
.majorCode = major_opcode,
};
TRY(encode(client_info.output_buffer, error));
return BAN::Error::from_errno(ENOENT);
}
return *it->value; switch (op_minor)
};
const auto get_drawable_info =
[](Object& object) -> DrawableInfo
{
DrawableInfo info;
switch (object.type)
{
case Object::Type::Window:
{
auto& window = object.object.get<Object::Window>();
auto& texture = window.texture();
info.data = { reinterpret_cast<uint8_t*>(texture.pixels().data()), texture.pixels().size() * 4 };
info.w = texture.width();
info.h = texture.height();
info.depth = window.depth;
break;
}
case Object::Type::Pixmap:
{
auto& pixmap = object.object.get<Object::Pixmap>();
info.data = pixmap.data;
info.w = pixmap.width;
info.h = pixmap.height;
info.depth = pixmap.depth;
break;
}
default:
ASSERT_NOT_REACHED();
}
return info;
};
switch (packet[1])
{ {
case X_ShmQueryVersion: case X_ShmQueryVersion:
{ {
@ -200,7 +135,7 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
dprintln("ShmDetach"); dprintln("ShmDetach");
dprintln(" shmseg: {}", request.shmseg); dprintln(" shmseg: {}", request.shmseg);
void* shm_segment = TRY(get_shmseg(request.shmseg)); void* shm_segment = TRY(get_shmseg(client_info, request.shmseg, op_major, op_minor));
shmdt(shm_segment); shmdt(shm_segment);
client_info.objects.remove(request.shmseg); client_info.objects.remove(request.shmseg);
@ -231,17 +166,14 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
dprintln(" offset: {}", request.offset); dprintln(" offset: {}", request.offset);
#endif #endif
void* shm_segment = TRY(get_shmseg(request.shmseg)); void* shm_segment = TRY(get_shmseg(client_info, request.shmseg, op_major, op_minor));
auto& object = TRY_REF(get_drawable(request.drawable)); auto [out_data, out_w, out_h, out_depth] = TRY(get_drawable_info(client_info, request.drawable, op_major, op_minor));
auto [out_data, out_w, out_h, out_depth] = get_drawable_info(object);
auto& gc_object = *g_objects[request.gc]; const auto& gc = TRY_REF(get_gc(client_info, request.gc, op_major, op_minor));
ASSERT(gc_object.type == Object::Type::GraphicsContext);
auto& gc = gc_object.object.get<Object::GraphicsContext>();
put_image({ put_image({
.out_data = out_data.data(), .out_data = out_data,
.out_x = request.dstX, .out_x = request.dstX,
.out_y = request.dstY, .out_y = request.dstY,
.out_w = out_w, .out_w = out_w,
@ -260,7 +192,7 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
.gc = gc, .gc = gc,
}); });
if (object.type == Object::Type::Window) if (g_objects[request.drawable]->type == Object::Type::Window)
invalidate_window(request.drawable, request.dstX, request.dstY, request.srcWidth, request.srcHeight); invalidate_window(request.drawable, request.dstX, request.dstY, request.srcWidth, request.srcHeight);
if (request.sendEvent) if (request.sendEvent)
@ -292,16 +224,15 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
dprintln(" shmseg: {}", request.shmseg); dprintln(" shmseg: {}", request.shmseg);
dprintln(" offset: {}", request.offset); dprintln(" offset: {}", request.offset);
void* shm_segment = TRY(get_shmseg(request.shmseg)); void* shm_segment = TRY(get_shmseg(client_info, request.shmseg, op_major, op_minor));
auto& object = TRY_REF(get_drawable(request.drawable)); auto [in_data, in_w, in_h, in_depth] = TRY(get_drawable_info(client_info, request.drawable, op_major, op_minor));
auto [in_data, in_w, in_h, in_depth] = get_drawable_info(object);
const auto dwords = image_dwords(request.width, request.height, in_depth); const auto dwords = image_dwords(request.width, request.height, in_depth);
get_image({ get_image({
.out_data = (uint8_t*)shm_segment + request.offset, .out_data = (uint8_t*)shm_segment + request.offset,
.in_data = in_data.data(), .in_data = in_data,
.in_x = request.x, .in_x = request.x,
.in_y = request.y, .in_y = request.y,
.in_w = in_w, .in_w = in_w,
@ -339,7 +270,7 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
ASSERT(request.depth == 24 || request.depth == 32); ASSERT(request.depth == 24 || request.depth == 32);
void* shm_segment = TRY(get_shmseg(request.shmseg)); void* shm_segment = TRY(get_shmseg(client_info, request.shmseg, op_major, op_minor));
TRY(client_info.objects.insert(request.pid)); TRY(client_info.objects.insert(request.pid));
TRY(g_objects.insert( TRY(g_objects.insert(

View File

@ -1,6 +1,7 @@
#include "Base.h" #include "Base.h"
#include "Definitions.h" #include "Definitions.h"
#include "Font.h" #include "Font.h"
#include "SafeGetters.h"
#include "Utils.h" #include "Utils.h"
#include <BAN/Endianness.h> #include <BAN/Endianness.h>
@ -500,76 +501,6 @@ static bool matches_pattern(const char* pattern, const char* string)
return *string ? false : true; return *string ? false : true;
} }
struct DrawableInfo
{
uint32_t* out_data_u32;
uint32_t out_w, out_h;
};
BAN::ErrorOr<DrawableInfo> get_drawable_info(Client& client_info, CARD32 drawable, BYTE opcode)
{
auto drawable_it = g_objects.find(drawable);
if (drawable_it == g_objects.end() || (drawable_it->value->type != Object::Type::Window && drawable_it->value->type != Object::Type::Pixmap))
{
xError error {
.type = X_Error,
.errorCode = BadDrawable,
.sequenceNumber = client_info.sequence,
.resourceID = drawable,
.minorCode = 0,
.majorCode = opcode,
};
TRY(encode(client_info.output_buffer, error));
return BAN::Error::from_errno(ENOENT);
}
DrawableInfo info;
switch (drawable_it->value->type)
{
case Object::Type::Window:
{
auto& texture = drawable_it->value->object.get<Object::Window>().texture();
info.out_data_u32 = texture.pixels().data();
info.out_w = texture.width();
info.out_h = texture.height();
break;
}
case Object::Type::Pixmap:
{
auto& pixmap = drawable_it->value->object.get<Object::Pixmap>();
info.out_data_u32 = reinterpret_cast<uint32_t*>(pixmap.data.data());
info.out_w = pixmap.width;
info.out_h = pixmap.height;
break;
}
default:
ASSERT_NOT_REACHED();
}
return info;
}
static BAN::ErrorOr<Object::GraphicsContext&> get_gc(Client& client_info, CARD32 gc, BYTE opcode)
{
auto it = g_objects.find(gc);
if (it == g_objects.end() || it->value->type != Object::Type::GraphicsContext)
{
xError error {
.type = X_Error,
.errorCode = BadGC,
.sequenceNumber = client_info.sequence,
.resourceID = gc,
.minorCode = 0,
.majorCode = opcode,
};
TRY(encode(client_info.output_buffer, error));
return BAN::Error::from_errno(ENOENT);
}
return it->value->object.get<Object::GraphicsContext>();
}
static BAN::ErrorOr<BAN::RefPtr<PCFFont>> get_fontable(Client& client_info, CARD32 fid, BYTE opcode) static BAN::ErrorOr<BAN::RefPtr<PCFFont>> get_fontable(Client& client_info, CARD32 fid, BYTE opcode)
{ {
auto it = g_objects.find(fid); auto it = g_objects.find(fid);
@ -809,7 +740,7 @@ BAN::ErrorOr<void> poly_text(Client& client_info, BAN::ConstByteSpan packet, boo
dprintln(" x: {}", request.x); dprintln(" x: {}", request.x);
dprintln(" y: {}", request.y); dprintln(" y: {}", request.y);
auto [out_data_u32, out_w, out_h] = TRY(get_drawable_info(client_info, request.drawable, opcode)); auto [out_data_u32, out_w, out_h, _] = TRY(get_drawable_info(client_info, request.drawable, opcode));
const auto& gc = TRY_REF(get_gc(client_info, request.gc, opcode)); const auto& gc = TRY_REF(get_gc(client_info, request.gc, opcode));
@ -880,7 +811,7 @@ BAN::ErrorOr<void> image_text(Client& client_info, BAN::ConstByteSpan packet, bo
dprintln(" x: {}", request.x); dprintln(" x: {}", request.x);
dprintln(" y: {}", request.y); dprintln(" y: {}", request.y);
auto [out_data_u32, out_w, out_h] = TRY(get_drawable_info(client_info, request.drawable, opcode)); auto [out_data_u32, out_w, out_h, _] = TRY(get_drawable_info(client_info, request.drawable, opcode));
const auto& gc = TRY_REF(get_gc(client_info, request.gc, opcode)); const auto& gc = TRY_REF(get_gc(client_info, request.gc, opcode));

111
xbanan/SafeGetters.cpp Normal file
View File

@ -0,0 +1,111 @@
#include "SafeGetters.h"
#include "Utils.h"
#include <X11/X.h>
BAN::ErrorOr<Object::Window&> get_window(Client& client_info, CARD32 wid, BYTE op_major, BYTE op_minor)
{
auto it = g_objects.find(wid);
if (it == g_objects.end() || it->value->type != Object::Type::Window)
{
xError error {
.type = X_Error,
.errorCode = BadWindow,
.sequenceNumber = client_info.sequence,
.resourceID = wid,
.minorCode = op_minor,
.majorCode = op_major,
};
TRY(encode(client_info.output_buffer, error));
return BAN::Error::from_errno(ENOENT);
}
return it->value->object.get<Object::Window>();
}
BAN::ErrorOr<Object::Pixmap&> get_pixmap(Client& client_info, CARD32 pid, BYTE op_major, BYTE op_minor)
{
auto it = g_objects.find(pid);
if (it == g_objects.end() || it->value->type != Object::Type::Pixmap)
{
xError error {
.type = X_Error,
.errorCode = BadPixmap,
.sequenceNumber = client_info.sequence,
.resourceID = pid,
.minorCode = op_minor,
.majorCode = op_major,
};
TRY(encode(client_info.output_buffer, error));
return BAN::Error::from_errno(ENOENT);
}
return it->value->object.get<Object::Pixmap>();
}
BAN::ErrorOr<Object::GraphicsContext&> get_gc(Client& client_info, CARD32 gc, BYTE op_major, BYTE op_minor)
{
auto it = g_objects.find(gc);
if (it == g_objects.end() || it->value->type != Object::Type::GraphicsContext)
{
xError error {
.type = X_Error,
.errorCode = BadGC,
.sequenceNumber = client_info.sequence,
.resourceID = gc,
.minorCode = op_minor,
.majorCode = op_major,
};
TRY(encode(client_info.output_buffer, error));
return BAN::Error::from_errno(ENOENT);
}
return it->value->object.get<Object::GraphicsContext>();
}
BAN::ErrorOr<DrawableInfo> get_drawable_info(Client& client_info, CARD32 drawable, BYTE op_major, BYTE op_minor)
{
auto drawable_it = g_objects.find(drawable);
if (drawable_it == g_objects.end() || (drawable_it->value->type != Object::Type::Window && drawable_it->value->type != Object::Type::Pixmap))
{
xError error {
.type = X_Error,
.errorCode = BadDrawable,
.sequenceNumber = client_info.sequence,
.resourceID = drawable,
.minorCode = op_minor,
.majorCode = op_major,
};
TRY(encode(client_info.output_buffer, error));
return BAN::Error::from_errno(ENOENT);
}
DrawableInfo info;
switch (drawable_it->value->type)
{
case Object::Type::Window:
{
auto& window = drawable_it->value->object.get<Object::Window>();
auto& texture = window.texture();
info.data_u32 = texture.pixels().data();
info.w = texture.width();
info.h = texture.height();
info.depth = window.depth;
break;
}
case Object::Type::Pixmap:
{
auto& pixmap = drawable_it->value->object.get<Object::Pixmap>();
info.data_u32 = reinterpret_cast<uint32_t*>(pixmap.data.data());
info.w = pixmap.width;
info.h = pixmap.height;
info.depth = pixmap.depth;
break;
}
default:
ASSERT_NOT_REACHED();
}
return info;
}

15
xbanan/SafeGetters.h Normal file
View File

@ -0,0 +1,15 @@
#pragma once
#include "Definitions.h"
struct DrawableInfo
{
uint32_t* data_u32;
uint32_t w, h;
uint8_t depth;
};
BAN::ErrorOr<Object::Window&> get_window(Client& client_info, CARD32 wid, BYTE op_major, BYTE op_minor = 0);
BAN::ErrorOr<Object::Pixmap&> get_pixmap(Client& client_info, CARD32 pid, BYTE op_major, BYTE op_minor = 0);
BAN::ErrorOr<Object::GraphicsContext&> get_gc(Client& client_info, CARD32 gc, BYTE op_major, BYTE op_minor = 0);
BAN::ErrorOr<DrawableInfo> get_drawable_info(Client& client_info, CARD32 drawable, BYTE op_major, BYTE op_minor = 0);