Compare commits
2 Commits
poll
...
40c002323e
| Author | SHA1 | Date | |
|---|---|---|---|
| 40c002323e | |||
| 0e0624ceb6 |
@@ -12,6 +12,7 @@
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
struct Selection
|
||||
{
|
||||
@@ -158,6 +159,16 @@ static const char* s_opcode_to_name[] {
|
||||
[X_NoOperation] = "X_NoOperation",
|
||||
};
|
||||
|
||||
void register_display(int32_t x, int32_t y, uint32_t width, uint32_t height)
|
||||
{
|
||||
MUST(g_displays.push_back({
|
||||
.x = x,
|
||||
.y = y,
|
||||
.w = width,
|
||||
.h = height,
|
||||
}));
|
||||
}
|
||||
|
||||
uint32_t Object::Window::full_event_mask() const
|
||||
{
|
||||
uint32_t full_event_mask = 0;
|
||||
@@ -199,9 +210,9 @@ BAN::ErrorOr<void> setup_client_conneciton(Client& client_info, const xConnClien
|
||||
xConnSetupPrefix setup_prefix {
|
||||
.success = 1,
|
||||
.lengthReason = 0, // wtf is this
|
||||
.majorVersion = client_prefix.majorVersion,
|
||||
.minorVersion = client_prefix.minorVersion,
|
||||
.length = 8 + 2*format_count + (8 + 0 + sz_xWindowRoot + sz_xDepth + sz_xVisualType) / 4,
|
||||
.majorVersion = 11,
|
||||
.minorVersion = 0,
|
||||
.length = 8 + 2 * format_count + (8 + 0 + sz_xWindowRoot + sz_xDepth + sz_xVisualType) / 4,
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, setup_prefix));
|
||||
|
||||
@@ -1362,15 +1373,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
||||
CARD16 width, height;
|
||||
CARD8 depth;
|
||||
|
||||
if (drawable_id == g_root.windowId)
|
||||
{
|
||||
width = g_root.pixWidth;
|
||||
height = g_root.pixHeight;
|
||||
depth = g_root.rootDepth;
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
else if (drawable.type == Object::Type::Window)
|
||||
if (drawable.type == Object::Type::Window)
|
||||
{
|
||||
const auto& window = drawable.object.get<Object::Window>();
|
||||
width = window.width;
|
||||
@@ -1813,9 +1816,9 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
||||
(void)TRY_REF(get_window(client_info, wid, X_SendEvent));
|
||||
|
||||
Client* target_client = nullptr;
|
||||
for (auto& [_, thingy] : g_pollables)
|
||||
for (auto& [_, thingy] : g_epoll_thingies)
|
||||
{
|
||||
if (thingy.type != Pollable::Type::Client)
|
||||
if (thingy.type != EpollThingy::Type::Client)
|
||||
continue;
|
||||
auto& other_client = thingy.value.get<Client>();
|
||||
if (!other_client.objects.contains(wid))
|
||||
@@ -1937,11 +1940,47 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
||||
case X_GrabServer:
|
||||
{
|
||||
g_server_grabber_fd = client_info.fd;
|
||||
|
||||
for (const auto& [_, thingy] : g_epoll_thingies)
|
||||
{
|
||||
if (thingy.type != EpollThingy::Type::Client)
|
||||
continue;
|
||||
|
||||
auto& other_client = thingy.value.get<Client>();
|
||||
if (client_info.fd == other_client.fd)
|
||||
continue;
|
||||
|
||||
uint32_t events = 0;
|
||||
if (other_client.has_epollout)
|
||||
events |= EPOLLOUT;
|
||||
|
||||
epoll_event event { .events = events, .data = { .fd = other_client.fd } };
|
||||
epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, other_client.fd, &event);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case X_UngrabServer:
|
||||
{
|
||||
g_server_grabber_fd = -1;
|
||||
|
||||
for (const auto& [_, thingy] : g_epoll_thingies)
|
||||
{
|
||||
if (thingy.type != EpollThingy::Type::Client)
|
||||
continue;
|
||||
|
||||
auto& other_client = thingy.value.get<Client>();
|
||||
if (client_info.fd == other_client.fd)
|
||||
continue;
|
||||
|
||||
uint32_t events = EPOLLIN;
|
||||
if (other_client.has_epollout)
|
||||
events |= EPOLLOUT;
|
||||
|
||||
epoll_event event { .events = events, .data = { .fd = other_client.fd } };
|
||||
epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, other_client.fd, &event);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case X_QueryPointer:
|
||||
|
||||
@@ -140,6 +140,7 @@ struct Client
|
||||
};
|
||||
int fd;
|
||||
State state;
|
||||
bool has_epollout { false };
|
||||
bool has_bigrequests { false };
|
||||
CARD16 sequence { 0 };
|
||||
BAN::Optional<uint32_t> pid;
|
||||
@@ -148,7 +149,7 @@ struct Client
|
||||
BAN::HashSet<CARD32> objects;
|
||||
};
|
||||
|
||||
struct Pollable
|
||||
struct EpollThingy
|
||||
{
|
||||
enum class Type
|
||||
{
|
||||
@@ -160,6 +161,12 @@ struct Pollable
|
||||
BAN::Variant<Client, void*> value;
|
||||
};
|
||||
|
||||
struct DisplayInfo
|
||||
{
|
||||
int32_t x, y;
|
||||
uint32_t w, h;
|
||||
};
|
||||
|
||||
extern const xPixmapFormat g_formats[6];
|
||||
extern const xDepth g_depth;
|
||||
extern const xVisualType g_visual;
|
||||
@@ -171,6 +178,11 @@ extern BAN::HashMap<BAN::String, ATOM> g_atoms_name_to_id;
|
||||
extern BAN::HashMap<ATOM, BAN::String> g_atoms_id_to_name;
|
||||
extern ATOM g_atom_value;
|
||||
|
||||
extern BAN::HashMap<int, Pollable> g_pollables;
|
||||
extern int g_epoll_fd;
|
||||
extern BAN::HashMap<int, EpollThingy> g_epoll_thingies;
|
||||
|
||||
extern int g_server_grabber_fd;
|
||||
|
||||
extern BAN::Vector<DisplayInfo> g_displays;
|
||||
|
||||
extern CARD32 g_next_global_id;
|
||||
|
||||
@@ -7,18 +7,23 @@
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
void register_event_fd(int fd, void* data)
|
||||
{
|
||||
MUST(g_pollables.insert(fd, {
|
||||
.type = Pollable::Type::Event,
|
||||
epoll_event event { .events = EPOLLIN, .data = { .fd = fd } };
|
||||
epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, fd, &event);
|
||||
|
||||
MUST(g_epoll_thingies.insert(fd, {
|
||||
.type = EpollThingy::Type::Event,
|
||||
.value = data,
|
||||
}));
|
||||
}
|
||||
|
||||
void unregister_event_fd(int fd)
|
||||
{
|
||||
g_pollables.remove(fd);
|
||||
epoll_ctl(g_epoll_fd, EPOLL_CTL_DEL, fd, nullptr);
|
||||
g_epoll_thingies.remove(fd);
|
||||
}
|
||||
|
||||
void on_window_close_event(WINDOW wid)
|
||||
|
||||
@@ -6,12 +6,64 @@
|
||||
|
||||
#include <time.h>
|
||||
|
||||
struct RANDRDisplay
|
||||
{
|
||||
CARD32 crtc_id;
|
||||
CARD32 output_id;
|
||||
CARD32 mode_id;
|
||||
ATOM name_atom;
|
||||
BAN::String output_str;
|
||||
BAN::String mode_str;
|
||||
const DisplayInfo& info;
|
||||
};
|
||||
|
||||
static BAN::Vector<RANDRDisplay> s_randr_displays;
|
||||
static CARD32 s_timestamp { 0 };
|
||||
|
||||
static void initialize_displays()
|
||||
{
|
||||
for (size_t i = 0; i < g_displays.size(); i++)
|
||||
{
|
||||
auto name = MUST(BAN::String::formatted("B-OUT-{}", i));
|
||||
|
||||
const auto name_atom = g_atom_value++;
|
||||
MUST(g_atoms_name_to_id.insert(name, name_atom));
|
||||
MUST(g_atoms_id_to_name.insert(name_atom, name));
|
||||
|
||||
MUST(s_randr_displays.push_back({
|
||||
.crtc_id = g_next_global_id++,
|
||||
.output_id = g_next_global_id++,
|
||||
.mode_id = g_next_global_id++,
|
||||
.name_atom = name_atom,
|
||||
.output_str = BAN::move(name),
|
||||
.mode_str = MUST(BAN::String::formatted("{}x{}", g_displays[i].w, g_displays[i].h)),
|
||||
.info = g_displays[i],
|
||||
}));
|
||||
}
|
||||
|
||||
s_timestamp = time(nullptr);
|
||||
}
|
||||
|
||||
static const RANDRDisplay& find_display_by_output(CARD32 output)
|
||||
{
|
||||
for (const auto& display : s_randr_displays)
|
||||
if (display.output_id == output)
|
||||
return display;
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
static const RANDRDisplay& find_display_by_crtc(CARD32 crtc)
|
||||
{
|
||||
for (const auto& display : s_randr_displays)
|
||||
if (display.crtc_id == crtc)
|
||||
return display;
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpan packet)
|
||||
{
|
||||
static CARD32 crtc_id = 5;
|
||||
static CARD32 output_id = 6;
|
||||
static CARD32 mode_id = 7;
|
||||
static CARD32 timestamp = time(nullptr);
|
||||
if (s_randr_displays.empty())
|
||||
initialize_displays();
|
||||
|
||||
static xRenderTransform transform {
|
||||
1 << 16, 0, 0,
|
||||
@@ -61,14 +113,14 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
|
||||
.setOfRotations = RR_Rotate_0,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = 3,
|
||||
.root = g_root.windowId,
|
||||
.timestamp = timestamp,
|
||||
.configTimestamp = timestamp,
|
||||
.nSizes = 1,
|
||||
.sizeID = 0,
|
||||
.rotation = RR_Rotate_0,
|
||||
.rate = 60,
|
||||
.nrateEnts = 1,
|
||||
.root = g_root.windowId,
|
||||
.timestamp = s_timestamp,
|
||||
.configTimestamp = s_timestamp,
|
||||
.nSizes = 1,
|
||||
.sizeID = 0,
|
||||
.rotation = RR_Rotate_0,
|
||||
.rate = 60,
|
||||
.nrateEnts = 1,
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, reply));
|
||||
|
||||
@@ -115,55 +167,63 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
|
||||
dprintln("RRGetScreenResources{}", current ? "Current" : "");
|
||||
dprintln(" window: {}", request.window);
|
||||
|
||||
const auto mode_name = TRY(BAN::String::formatted("{}x{}", g_root.pixWidth, g_root.pixHeight));
|
||||
size_t mode_name_bytes = 0;
|
||||
for (const auto& display : s_randr_displays)
|
||||
mode_name_bytes += display.mode_str.size();
|
||||
|
||||
xRRGetScreenResourcesReply reply {
|
||||
.type = X_Reply,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = static_cast<CARD32>(1 + 1 + 8 + (mode_name.size() + 3) / 4),
|
||||
.timestamp = timestamp,
|
||||
.configTimestamp = timestamp,
|
||||
.nCrtcs = 1,
|
||||
.nOutputs = 1,
|
||||
.nModes = 1,
|
||||
.nbytesNames = static_cast<CARD16>(mode_name.size()),
|
||||
.length = static_cast<CARD32>(s_randr_displays.size() * (1 + 1 + 8) + (mode_name_bytes + 3) / 4),
|
||||
.timestamp = s_timestamp,
|
||||
.configTimestamp = s_timestamp,
|
||||
.nCrtcs = static_cast<CARD16>(s_randr_displays.size()),
|
||||
.nOutputs = static_cast<CARD16>(s_randr_displays.size()),
|
||||
.nModes = static_cast<CARD16>(s_randr_displays.size()),
|
||||
.nbytesNames = static_cast<CARD16>(mode_name_bytes),
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, reply));
|
||||
|
||||
TRY(encode(client_info.output_buffer, crtc_id));
|
||||
for (const auto& display : s_randr_displays)
|
||||
TRY(encode(client_info.output_buffer, display.crtc_id));
|
||||
|
||||
TRY(encode(client_info.output_buffer, output_id));
|
||||
for (const auto& display : s_randr_displays)
|
||||
TRY(encode(client_info.output_buffer, display.output_id));
|
||||
|
||||
const CARD16 hsync_start = g_root.pixWidth;
|
||||
const CARD16 hsync_end = g_root.pixWidth + 1;
|
||||
const CARD16 htotal = g_root.pixWidth + 1;
|
||||
for (const auto& display : s_randr_displays)
|
||||
{
|
||||
const CARD16 hsync_start = display.info.w;
|
||||
const CARD16 hsync_end = display.info.w + 1;
|
||||
const CARD16 htotal = display.info.w + 1;
|
||||
|
||||
const CARD16 vsync_start = g_root.pixHeight;
|
||||
const CARD16 vsync_end = g_root.pixHeight + 1;
|
||||
const CARD16 vtotal = g_root.pixHeight + 1;
|
||||
const CARD16 vsync_start = display.info.h;
|
||||
const CARD16 vsync_end = display.info.h + 1;
|
||||
const CARD16 vtotal = display.info.h + 1;
|
||||
|
||||
const CARD32 clock = htotal * vtotal * 60;
|
||||
const CARD32 clock = htotal * vtotal * 60;
|
||||
|
||||
xRRModeInfo mode_info {
|
||||
.id = mode_id,
|
||||
.width = g_root.pixWidth,
|
||||
.height = g_root.pixHeight,
|
||||
.dotClock = clock,
|
||||
.hSyncStart = hsync_start,
|
||||
.hSyncEnd = hsync_end,
|
||||
.hTotal = htotal,
|
||||
.hSkew = 0,
|
||||
.vSyncStart = vsync_start,
|
||||
.vSyncEnd = vsync_end,
|
||||
.vTotal = vtotal,
|
||||
.nameLength = static_cast<CARD16>(mode_name.size()),
|
||||
.modeFlags = RR_HSyncPositive | RR_VSyncPositive,
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, mode_info));
|
||||
xRRModeInfo mode_info {
|
||||
.id = display.mode_id,
|
||||
.width = static_cast<CARD16>(display.info.w),
|
||||
.height = static_cast<CARD16>(display.info.h),
|
||||
.dotClock = clock,
|
||||
.hSyncStart = hsync_start,
|
||||
.hSyncEnd = hsync_end,
|
||||
.hTotal = htotal,
|
||||
.hSkew = 0,
|
||||
.vSyncStart = vsync_start,
|
||||
.vSyncEnd = vsync_end,
|
||||
.vTotal = vtotal,
|
||||
.nameLength = static_cast<CARD16>(display.mode_str.size()),
|
||||
.modeFlags = RR_HSyncPositive | RR_VSyncPositive,
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, mode_info));
|
||||
}
|
||||
|
||||
TRY(encode(client_info.output_buffer, mode_name));
|
||||
for (size_t i = 0; (mode_name.size() + i) % 4; i++)
|
||||
TRY(encode(client_info.output_buffer, '\0'));
|
||||
for (const auto& display : s_randr_displays)
|
||||
TRY(encode(client_info.output_buffer, display.mode_str));
|
||||
while (client_info.output_buffer.size() % 4)
|
||||
TRY(encode<BYTE>(client_info.output_buffer, 0));
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -175,27 +235,31 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
|
||||
dprintln(" output: {}", request.output);
|
||||
dprintln(" configTimestamp: {}", request.configTimestamp);
|
||||
|
||||
const auto& display = find_display_by_output(request.output);
|
||||
|
||||
xRRGetOutputInfoReply reply {
|
||||
.type = X_Reply,
|
||||
.status = Success,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = 1 + 1 + 1 + 2,
|
||||
.timestamp = timestamp,
|
||||
.crtc = crtc_id,
|
||||
.mmWidth = g_root.mmWidth,
|
||||
.mmHeight = g_root.mmHeight,
|
||||
.connection = RR_Connected,
|
||||
.subpixelOrder = SubPixelUnknown,
|
||||
.nCrtcs = 1,
|
||||
.nModes = 1,
|
||||
.nPreferred = 1,
|
||||
.nClones = 0,
|
||||
.nameLength = 5,
|
||||
.type = X_Reply,
|
||||
.status = Success,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = static_cast<CARD32>(1 + 1 + 1 + (display.output_str.size() + 3) / 4),
|
||||
.timestamp = s_timestamp,
|
||||
.crtc = display.crtc_id,
|
||||
.mmWidth = display.info.w * 254 / 960, // 96 DPI
|
||||
.mmHeight = display.info.h * 254 / 960, // 96 DPI
|
||||
.connection = RR_Connected,
|
||||
.subpixelOrder = SubPixelUnknown,
|
||||
.nCrtcs = 1,
|
||||
.nModes = 1,
|
||||
.nPreferred = 1,
|
||||
.nClones = 0,
|
||||
.nameLength = static_cast<CARD16>(display.output_str.size()),
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, reply));
|
||||
TRY(encode(client_info.output_buffer, crtc_id));
|
||||
TRY(encode(client_info.output_buffer, mode_id));
|
||||
TRY(encode(client_info.output_buffer, "B-OUT\0\0\0"_sv));
|
||||
TRY(encode(client_info.output_buffer, display.crtc_id));
|
||||
TRY(encode(client_info.output_buffer, display.mode_id));
|
||||
TRY(encode(client_info.output_buffer, display.output_str));
|
||||
while (client_info.output_buffer.size() % 4)
|
||||
TRY(encode<BYTE>(client_info.output_buffer, 0));
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -250,25 +314,27 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
|
||||
dprintln(" crtc: {}", request.crtc);
|
||||
dprintln(" configTimestamp: {}", request.configTimestamp);
|
||||
|
||||
const auto& display = find_display_by_crtc(request.crtc);
|
||||
|
||||
xRRGetCrtcInfoReply reply {
|
||||
.type = X_Reply,
|
||||
.status = Success,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = 2,
|
||||
.timestamp = timestamp,
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = g_root.pixWidth,
|
||||
.height = g_root.pixHeight,
|
||||
.mode = mode_id,
|
||||
.timestamp = s_timestamp,
|
||||
.x = static_cast<INT16>(display.info.x),
|
||||
.y = static_cast<INT16>(display.info.y),
|
||||
.width = static_cast<CARD16>(display.info.w),
|
||||
.height = static_cast<CARD16>(display.info.h),
|
||||
.mode = display.mode_id,
|
||||
.rotation = RR_Rotate_0,
|
||||
.rotations = RR_Rotate_0,
|
||||
.nOutput = 1,
|
||||
.nPossibleOutput = 1,
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, reply));
|
||||
TRY(encode(client_info.output_buffer, output_id));
|
||||
TRY(encode(client_info.output_buffer, output_id));
|
||||
TRY(encode(client_info.output_buffer, display.output_id));
|
||||
TRY(encode(client_info.output_buffer, display.output_id));
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -285,13 +351,13 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
|
||||
dprintln(" mode: {}", request.mode);
|
||||
dprintln(" rotation: {}", request.rotation);
|
||||
|
||||
timestamp = time(nullptr);
|
||||
s_timestamp = time(nullptr);
|
||||
xRRSetCrtcConfigReply reply {
|
||||
.type = X_Reply,
|
||||
.status = Success,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = 0,
|
||||
.newTimestamp = timestamp,
|
||||
.newTimestamp = s_timestamp,
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, reply));
|
||||
|
||||
@@ -301,15 +367,15 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
|
||||
{
|
||||
auto request = decode<xRRGetCrtcGammaSizeReq>(packet).value();
|
||||
|
||||
dprintln("RRGetCrtcGammaSize");
|
||||
dprintln(" crtc: {}", request.crtc);
|
||||
dwarnln("RRGetCrtcGammaSize");
|
||||
dwarnln(" crtc: {}", request.crtc);
|
||||
|
||||
xRRGetCrtcGammaSizeReply reply {
|
||||
.type = X_Reply,
|
||||
.status = Success,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = 0,
|
||||
.size = 1,
|
||||
.type = X_Reply,
|
||||
.status = Success,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = 0,
|
||||
.size = 256,
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, reply));
|
||||
|
||||
@@ -323,17 +389,16 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
|
||||
dprintln(" crtc: {}", request.crtc);
|
||||
|
||||
xRRGetCrtcGammaReply reply {
|
||||
.type = X_Reply,
|
||||
.status = Success,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = 2,
|
||||
.size = 1,
|
||||
.type = X_Reply,
|
||||
.status = Success,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = (6 * 256) / 4,
|
||||
.size = 256,
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, reply));
|
||||
TRY(encode<CARD16>(client_info.output_buffer, 1));
|
||||
TRY(encode<CARD16>(client_info.output_buffer, 1));
|
||||
TRY(encode<CARD16>(client_info.output_buffer, 1));
|
||||
TRY(encode<CARD16>(client_info.output_buffer, 0));
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
for (size_t j = 0; j < 256; j++)
|
||||
TRY(encode<CARD16>(client_info.output_buffer, j * 65535 / 255));
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -345,17 +410,17 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
|
||||
dprintln(" crtc: {}", request.crtc);
|
||||
|
||||
xRRGetCrtcTransformReply reply {
|
||||
.type = X_Reply,
|
||||
.status = Success,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = 16,
|
||||
.pendingTransform = transform,
|
||||
.hasTransforms = xFalse,
|
||||
.currentTransform = transform,
|
||||
.pendingNbytesFilter = 0,
|
||||
.pendingNparamsFilter = 0,
|
||||
.currentNbytesFilter = 0,
|
||||
.currentNparamsFilter = 0,
|
||||
.type = X_Reply,
|
||||
.status = Success,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = 16,
|
||||
.pendingTransform = transform,
|
||||
.hasTransforms = xFalse,
|
||||
.currentTransform = transform,
|
||||
.pendingNbytesFilter = 0,
|
||||
.pendingNparamsFilter = 0,
|
||||
.currentNbytesFilter = 0,
|
||||
.currentNparamsFilter = 0,
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, reply));
|
||||
|
||||
@@ -369,23 +434,23 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
|
||||
dprintln(" crtc: {}", request.crtc);
|
||||
|
||||
xRRGetPanningReply reply {
|
||||
.type = X_Reply,
|
||||
.status = Success,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = 1,
|
||||
.timestamp = timestamp,
|
||||
.left = 0,
|
||||
.top = 0,
|
||||
.width = 0,
|
||||
.height = 0,
|
||||
.track_left = 0,
|
||||
.track_top = 0,
|
||||
.track_width = 0,
|
||||
.track_height = 0,
|
||||
.border_left = 0,
|
||||
.border_top = 0,
|
||||
.border_right = 0,
|
||||
.border_bottom = 0,
|
||||
.type = X_Reply,
|
||||
.status = Success,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = 1,
|
||||
.timestamp = s_timestamp,
|
||||
.left = 0,
|
||||
.top = 0,
|
||||
.width = 0,
|
||||
.height = 0,
|
||||
.track_left = 0,
|
||||
.track_top = 0,
|
||||
.track_width = 0,
|
||||
.track_height = 0,
|
||||
.border_left = 0,
|
||||
.border_top = 0,
|
||||
.border_right = 0,
|
||||
.border_bottom = 0,
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, reply));
|
||||
|
||||
@@ -399,10 +464,10 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
|
||||
dprintln(" window: {}", request.window);
|
||||
|
||||
xRRGetOutputPrimaryReply reply {
|
||||
.type = X_Reply,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = 0,
|
||||
.output = output_id,
|
||||
.type = X_Reply,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = 0,
|
||||
.output = s_randr_displays.front().output_id,
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, reply));
|
||||
|
||||
@@ -416,10 +481,10 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
|
||||
dprintln(" window: {}", request.window);
|
||||
|
||||
xRRGetProvidersReply reply {
|
||||
.type = X_Reply,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = 0,
|
||||
.timestamp = timestamp,
|
||||
.type = X_Reply,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = 0,
|
||||
.timestamp = s_timestamp,
|
||||
.nProviders = 0,
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, reply));
|
||||
@@ -435,31 +500,33 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
|
||||
dprintln(" get_active: {}", request.get_active);
|
||||
|
||||
xRRGetMonitorsReply reply {
|
||||
.type = X_Reply,
|
||||
.type = X_Reply,
|
||||
.status = Success,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = 6 + 1,
|
||||
.timestamp = timestamp,
|
||||
.nmonitors = 1,
|
||||
.noutputs = 1,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = static_cast<CARD32>(6 * s_randr_displays.size() + s_randr_displays.size()),
|
||||
.timestamp = s_timestamp,
|
||||
.nmonitors = static_cast<CARD32>(s_randr_displays.size()),
|
||||
.noutputs = static_cast<CARD32>(s_randr_displays.size()),
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, reply));
|
||||
|
||||
xRRMonitorInfo monitor {
|
||||
.name = None,
|
||||
.primary = xTrue,
|
||||
.automatic = xTrue,
|
||||
.noutput = 1,
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = g_root.pixWidth,
|
||||
.height = g_root.pixHeight,
|
||||
.widthInMillimeters = g_root.mmWidth,
|
||||
.heightInMillimeters = g_root.mmHeight,
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, monitor));
|
||||
|
||||
TRY(encode(client_info.output_buffer, output_id));
|
||||
for (const auto& display : s_randr_displays)
|
||||
{
|
||||
xRRMonitorInfo monitor {
|
||||
.name = display.name_atom,
|
||||
.primary = (&display == &s_randr_displays.front()),
|
||||
.automatic = xTrue,
|
||||
.noutput = 1,
|
||||
.x = static_cast<INT16>(display.info.x),
|
||||
.y = static_cast<INT16>(display.info.y),
|
||||
.width = static_cast<CARD16>(display.info.w),
|
||||
.height = static_cast<CARD16>(display.info.h),
|
||||
.widthInMillimeters = display.info.w * 254 / 96, // 96 DPI
|
||||
.heightInMillimeters = display.info.h * 254 / 96, // 96 DPI
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, monitor));
|
||||
TRY(encode(client_info.output_buffer, display.output_id));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
template<typename F>
|
||||
static BAN::ErrorOr<void> for_each_client(uint32_t target_spec, const F& callback)
|
||||
{
|
||||
for (auto [fd, thingy] : g_pollables)
|
||||
for (const auto& [fd, thingy] : g_epoll_thingies)
|
||||
{
|
||||
if (thingy.type != Pollable::Type::Client)
|
||||
if (thingy.type != EpollThingy::Type::Client)
|
||||
continue;
|
||||
|
||||
Client& client_info = thingy.value.get<Client>();
|
||||
const auto& client_info = thingy.value.get<Client>();
|
||||
if (target_spec && (target_spec >> 20) != client_info.fd)
|
||||
continue;
|
||||
|
||||
@@ -61,7 +61,7 @@ BAN::ErrorOr<void> extension_xres(Client& client_info, BAN::ConstByteSpan packet
|
||||
{
|
||||
auto spec = decode<xXResClientIdSpec>(packet).value();
|
||||
|
||||
TRY(for_each_client(spec.client, [&](Client& client_info, uint32_t client_spec) -> BAN::ErrorOr<void> {
|
||||
TRY(for_each_client(spec.client, [&](const Client& client_info, uint32_t client_spec) -> BAN::ErrorOr<void> {
|
||||
if (spec.mask == None || (spec.mask & X_XResClientXIDMask))
|
||||
{
|
||||
xXResClientIdValue value {
|
||||
|
||||
@@ -47,7 +47,7 @@ enum class SystemCursorType
|
||||
struct PlatformOps
|
||||
{
|
||||
/* Do platform initialization */
|
||||
bool (*initialize)(uint32_t* width, uint32_t* height);
|
||||
bool (*initialize)();
|
||||
/* Handle pending events */
|
||||
void (*poll_events)(void*);
|
||||
/* Create a window with given size */
|
||||
@@ -74,3 +74,5 @@ struct PlatformOps
|
||||
void (*set_cursor)(PlatformWindow*, PlatformCursor*);
|
||||
};
|
||||
extern PlatformOps g_platform_ops;
|
||||
|
||||
void register_display(int32_t x, int32_t y, uint32_t width, uint32_t height);
|
||||
|
||||
@@ -69,7 +69,7 @@ static void* sdl3_thread(void*)
|
||||
|
||||
static void sdl3_initialize_keymap();
|
||||
|
||||
static bool sdl3_initialize(uint32_t* display_w, uint32_t* display_h)
|
||||
static bool sdl3_initialize()
|
||||
{
|
||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS))
|
||||
{
|
||||
@@ -77,15 +77,16 @@ static bool sdl3_initialize(uint32_t* display_w, uint32_t* display_h)
|
||||
return false;
|
||||
}
|
||||
|
||||
*display_w = *display_h = 0;
|
||||
|
||||
const SDL_DisplayID* display_ids = SDL_GetDisplays(nullptr);
|
||||
for (int i = 0; display_ids[i]; i++)
|
||||
{
|
||||
SDL_Rect rect;
|
||||
SDL_GetDisplayBounds(display_ids[i], &rect);
|
||||
*display_w = BAN::Math::max<uint32_t>(*display_w, rect.x + rect.w);
|
||||
*display_h = BAN::Math::max<uint32_t>(*display_h, rect.y + rect.h);
|
||||
if (!SDL_GetDisplayBounds(display_ids[i], &rect))
|
||||
{
|
||||
dwarnln("Could not display {} bounds: {}", SDL_GetError());
|
||||
continue;
|
||||
}
|
||||
register_display(rect.x, rect.y, rect.w, rect.h);
|
||||
}
|
||||
|
||||
sdl3_initialize_keymap();
|
||||
|
||||
@@ -28,7 +28,7 @@ struct BananCursor final : public PlatformCursor
|
||||
|
||||
static BAN::ErrorOr<void> bananos_initialize_keymap();
|
||||
|
||||
static bool bananos_initialize(uint32_t* display_w, uint32_t* display_h)
|
||||
static bool bananos_initialize()
|
||||
{
|
||||
auto attributes = LibGUI::Window::default_attributes;
|
||||
attributes.shown = false;
|
||||
@@ -40,8 +40,7 @@ static bool bananos_initialize(uint32_t* display_w, uint32_t* display_h)
|
||||
return false;
|
||||
}
|
||||
|
||||
*display_w = dummy_or_error.value()->width();
|
||||
*display_h = dummy_or_error.value()->height();
|
||||
register_display(0, 0, dummy_or_error.value()->width(), dummy_or_error.value()->height());
|
||||
|
||||
if (auto ret = bananos_initialize_keymap(); ret.is_error())
|
||||
{
|
||||
|
||||
246
xbanan/main.cpp
246
xbanan/main.cpp
@@ -5,8 +5,8 @@
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include <locale.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
@@ -19,6 +19,8 @@
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
CARD32 g_next_global_id { 1 };
|
||||
|
||||
const xPixmapFormat g_formats[6] {
|
||||
{
|
||||
.depth = 1,
|
||||
@@ -58,7 +60,7 @@ const xDepth g_depth {
|
||||
};
|
||||
|
||||
const xVisualType g_visual {
|
||||
.visualID = 1,
|
||||
.visualID = g_next_global_id++,
|
||||
.c_class = TrueColor,
|
||||
.bitsPerRGB = 8,
|
||||
.colormapEntries = 256,
|
||||
@@ -68,31 +70,34 @@ const xVisualType g_visual {
|
||||
};
|
||||
|
||||
xWindowRoot g_root {
|
||||
.windowId = 2,
|
||||
.windowId = g_next_global_id++,
|
||||
.defaultColormap = 0,
|
||||
.whitePixel = 0xFFFFFF,
|
||||
.blackPixel = 0x000000,
|
||||
.currentInputMask = 0,
|
||||
.pixWidth = 0,
|
||||
.pixHeight = 0,
|
||||
.mmWidth = 0,
|
||||
.mmWidth = 0,
|
||||
.mmHeight = 0,
|
||||
.minInstalledMaps = 1,
|
||||
.maxInstalledMaps = 1,
|
||||
.rootVisualID = g_visual.visualID,
|
||||
.backingStore = 0,
|
||||
.saveUnders = 0,
|
||||
.rootDepth = 24,
|
||||
.rootDepth = g_depth.depth,
|
||||
.nDepths = 1,
|
||||
};
|
||||
|
||||
BAN::Vector<DisplayInfo> g_displays;
|
||||
|
||||
BAN::HashMap<CARD32, BAN::UniqPtr<Object>> g_objects;
|
||||
|
||||
BAN::HashMap<BAN::String, ATOM> g_atoms_name_to_id;
|
||||
BAN::HashMap<ATOM, BAN::String> g_atoms_id_to_name;
|
||||
ATOM g_atom_value = XA_LAST_PREDEFINED + 1;
|
||||
|
||||
BAN::HashMap<int, Pollable> g_pollables;
|
||||
int g_epoll_fd;
|
||||
BAN::HashMap<int, EpollThingy> g_epoll_thingies;
|
||||
|
||||
int g_server_grabber_fd = -1;
|
||||
|
||||
@@ -154,6 +159,22 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_epoll_fd = epoll_create1(0);
|
||||
if (g_epoll_fd == -1)
|
||||
{
|
||||
perror("xbanan: epoll_create1");
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
epoll_event event { .events = EPOLLIN, .data = { .ptr = nullptr } };
|
||||
if (epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, server_sock, &event) == -1)
|
||||
{
|
||||
perror("xbanan: epoll_ctl");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#define APPEND_ATOM(name) do { \
|
||||
MUST(g_atoms_id_to_name.insert(name, #name##_sv.substring(3))); \
|
||||
MUST(g_atoms_name_to_id.insert(#name##_sv.substring(3), name)); \
|
||||
@@ -244,22 +265,62 @@ int main()
|
||||
APPEND_ATOM_CUSTOM(_NET_WM_WINDOW_TYPE_UTILITY);
|
||||
#undef APPEND_ATOM_CUSTOM
|
||||
|
||||
uint32_t display_w, display_h;
|
||||
if (!g_platform_ops.initialize(&display_w, &display_h))
|
||||
if (!g_platform_ops.initialize())
|
||||
return 1;
|
||||
g_root.pixWidth = display_w;
|
||||
g_root.pixHeight = display_h;
|
||||
g_root.mmWidth = static_cast<CARD16>(display_w * 254 / 960); // 96 DPI
|
||||
g_root.mmHeight = static_cast<CARD16>(display_h * 254 / 960); // 96 DPI
|
||||
|
||||
if (g_displays.empty())
|
||||
{
|
||||
dwarnln("No displays windows initilized");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t display_min_x { INT32_MAX }, display_min_y { INT32_MAX };
|
||||
int32_t display_max_x { INT32_MIN }, display_max_y { INT32_MIN };
|
||||
for (const auto& display : g_displays)
|
||||
{
|
||||
display_min_x = BAN::Math::min<int32_t>(display_min_x, display.x);
|
||||
display_min_y = BAN::Math::min<int32_t>(display_min_y, display.y);
|
||||
display_max_x = BAN::Math::max<int32_t>(display_max_x, display.x + display.w);
|
||||
display_max_y = BAN::Math::max<int32_t>(display_max_y, display.y + display.h);
|
||||
}
|
||||
|
||||
g_root.pixWidth = display_max_x - display_min_x;
|
||||
g_root.pixHeight = display_max_y - display_min_y;
|
||||
|
||||
g_root.mmWidth = g_root.pixWidth * 254 / 960; // 96 DPI
|
||||
g_root.mmHeight = g_root.pixHeight * 254 / 960; // 96 DPI
|
||||
|
||||
Client dummy_owner;
|
||||
MUST(g_objects.insert(g_root.windowId, MUST(BAN::UniqPtr<Object>::create(Object {
|
||||
.type = Object::Type::Window,
|
||||
.object = Object::Window {
|
||||
.owner = dummy_owner,
|
||||
.depth = g_root.rootDepth,
|
||||
.x = display_min_x,
|
||||
.y = display_min_y,
|
||||
.parent = None,
|
||||
.cursor = None,
|
||||
.c_class = InputOutput,
|
||||
.width = g_root.pixWidth,
|
||||
.height = g_root.pixHeight,
|
||||
.background = None,
|
||||
}
|
||||
}))));
|
||||
|
||||
MUST(g_objects.insert(g_visual.visualID,
|
||||
MUST(BAN::UniqPtr<Object>::create(Object {
|
||||
.type = Object::Type::Visual,
|
||||
}))
|
||||
));
|
||||
|
||||
printf("xbanan started\n");
|
||||
|
||||
const auto close_client =
|
||||
[](int client_fd)
|
||||
{
|
||||
auto& pollable = g_pollables[client_fd];
|
||||
ASSERT(pollable.type == Pollable::Type::Client);
|
||||
auto& client_info = pollable.value.get<Client>();
|
||||
auto& epoll_thingy = g_epoll_thingies[client_fd];
|
||||
ASSERT(epoll_thingy.type == EpollThingy::Type::Client);
|
||||
auto& client_info = epoll_thingy.value.get<Client>();
|
||||
|
||||
dprintln("client {} disconnected", client_fd);
|
||||
|
||||
@@ -311,68 +372,39 @@ int main()
|
||||
g_objects.remove(it);
|
||||
}
|
||||
|
||||
g_pollables.remove(client_fd);
|
||||
epoll_ctl(g_epoll_fd, EPOLL_CTL_DEL, client_fd, nullptr);
|
||||
g_epoll_thingies.remove(client_fd);
|
||||
close(client_fd);
|
||||
|
||||
if (g_server_grabber_fd == client_fd)
|
||||
if (client_fd == g_server_grabber_fd)
|
||||
{
|
||||
g_server_grabber_fd = -1;
|
||||
};
|
||||
|
||||
Client dummy_client {};
|
||||
MUST(g_objects.insert(g_root.windowId,
|
||||
MUST(BAN::UniqPtr<Object>::create(Object {
|
||||
.type = Object::Type::Window,
|
||||
.object = Object::Window {
|
||||
.owner = dummy_client,
|
||||
.mapped = true,
|
||||
.depth = g_root.rootDepth,
|
||||
.parent = None,
|
||||
.c_class = InputOutput,
|
||||
.width = g_root.pixWidth,
|
||||
.height = g_root.pixHeight,
|
||||
for (const auto& [_, thingy] : g_epoll_thingies)
|
||||
{
|
||||
if (thingy.type != EpollThingy::Type::Client)
|
||||
continue;
|
||||
|
||||
auto& other_client = thingy.value.get<Client>();
|
||||
|
||||
uint32_t events = EPOLLIN;
|
||||
if (other_client.has_epollout)
|
||||
events |= EPOLLOUT;
|
||||
|
||||
epoll_event event { .events = events, .data = { .fd = other_client.fd } };
|
||||
epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, other_client.fd, &event);
|
||||
}
|
||||
}
|
||||
}))
|
||||
));
|
||||
|
||||
MUST(g_objects.insert(g_visual.visualID,
|
||||
MUST(BAN::UniqPtr<Object>::create(Object {
|
||||
.type = Object::Type::Visual,
|
||||
}))
|
||||
));
|
||||
};
|
||||
|
||||
for (;;)
|
||||
{
|
||||
BAN::Vector<pollfd> pollfds;
|
||||
MUST(pollfds.reserve(g_pollables.size() + 1));
|
||||
MUST(pollfds.push_back({
|
||||
.fd = server_sock,
|
||||
.events = POLLIN,
|
||||
.revents = 0,
|
||||
}));
|
||||
for (auto& [fd, pollable] : g_pollables)
|
||||
epoll_event events[16];
|
||||
const int event_count = epoll_wait(g_epoll_fd, events, 16, -1);
|
||||
|
||||
for (int i = 0; i < event_count; i++)
|
||||
{
|
||||
short events = 0;
|
||||
if (g_server_grabber_fd == -1 || g_server_grabber_fd == fd)
|
||||
events |= POLLIN;
|
||||
if (pollable.type == Pollable::Type::Client && !pollable.value.get<Client>().output_buffer.empty())
|
||||
events |= POLLOUT;
|
||||
if (events == 0)
|
||||
continue;
|
||||
MUST(pollfds.push_back(pollfd {
|
||||
.fd = fd,
|
||||
.events = events,
|
||||
.revents = 0,
|
||||
}));
|
||||
}
|
||||
|
||||
const int event_count = poll(pollfds.data(), pollfds.size(), -1);
|
||||
|
||||
for (const auto& pollfd : pollfds)
|
||||
{
|
||||
if (pollfd.revents == 0)
|
||||
continue;
|
||||
|
||||
if (pollfd.fd == server_sock)
|
||||
if (events[i].data.ptr == nullptr)
|
||||
{
|
||||
int client_sock = accept(server_sock, nullptr, nullptr);
|
||||
if (client_sock == -1)
|
||||
@@ -390,8 +422,8 @@ int main()
|
||||
client_pid = client_cred.pid;
|
||||
#endif
|
||||
|
||||
MUST(g_pollables.insert(client_sock, {
|
||||
.type = Pollable::Type::Client,
|
||||
MUST(g_epoll_thingies.insert(client_sock, {
|
||||
.type = EpollThingy::Type::Client,
|
||||
.value = Client {
|
||||
.fd = client_sock,
|
||||
.state = Client::State::ConnectionSetup,
|
||||
@@ -399,32 +431,44 @@ int main()
|
||||
}
|
||||
}));
|
||||
|
||||
uint32_t events = 0;
|
||||
if (g_server_grabber_fd == -1)
|
||||
events |= EPOLLIN;
|
||||
|
||||
epoll_event event = { .events = events, .data = { .fd = client_sock } };
|
||||
if (epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, client_sock, &event) == -1)
|
||||
{
|
||||
perror("xbanan: epoll_ctl");
|
||||
close(client_sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
dprintln("client {} connected", client_sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto it = g_pollables.find(pollfd.fd);
|
||||
if (it == g_pollables.end())
|
||||
auto it = g_epoll_thingies.find(events[i].data.fd);
|
||||
if (it == g_epoll_thingies.end())
|
||||
continue;
|
||||
auto& pollable = it->value;
|
||||
auto& epoll_thingy = it->value;
|
||||
|
||||
if (pollable.type == Pollable::Type::Event)
|
||||
if (epoll_thingy.type == EpollThingy::Type::Event)
|
||||
{
|
||||
g_platform_ops.poll_events(pollable.value.get<void*>());
|
||||
g_platform_ops.poll_events(epoll_thingy.value.get<void*>());
|
||||
continue;
|
||||
}
|
||||
|
||||
ASSERT(pollable.type == Pollable::Type::Client);
|
||||
ASSERT(epoll_thingy.type == EpollThingy::Type::Client);
|
||||
|
||||
auto& client_info = pollable.value.get<Client>();
|
||||
auto& client_info = epoll_thingy.value.get<Client>();
|
||||
|
||||
if (pollfd.revents & POLLHUP)
|
||||
if (events[i].events & EPOLLHUP)
|
||||
{
|
||||
close_client(client_info.fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pollfd.revents & POLLOUT)
|
||||
if (events[i].events & EPOLLOUT)
|
||||
{
|
||||
const ssize_t nsend = send(
|
||||
client_info.fd,
|
||||
@@ -451,11 +495,28 @@ int main()
|
||||
);
|
||||
MUST(client_info.output_buffer.resize(client_info.output_buffer.size() - nsend));
|
||||
|
||||
if (client_info.output_buffer.empty())
|
||||
{
|
||||
uint32_t events = 0;
|
||||
if (g_server_grabber_fd == -1 || g_server_grabber_fd == client_info.fd)
|
||||
events |= EPOLLIN;
|
||||
|
||||
epoll_event event { .events = events, .data = { .fd = client_info.fd } };
|
||||
if (epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, client_info.fd, &event) == -1)
|
||||
{
|
||||
perror("xbanan: epoll_ctl");
|
||||
close_client(client_info.fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
client_info.has_epollout = false;
|
||||
}
|
||||
|
||||
send_done:
|
||||
(void)0;
|
||||
}
|
||||
|
||||
if (!(pollfd.revents & POLLIN))
|
||||
if (!(events[i].events & EPOLLIN))
|
||||
continue;
|
||||
|
||||
if (g_server_grabber_fd != -1 && g_server_grabber_fd != client_info.fd)
|
||||
@@ -567,5 +628,30 @@ int main()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iterator_invalidated:
|
||||
for (auto& [_, thingy] : g_epoll_thingies)
|
||||
{
|
||||
if (thingy.type != EpollThingy::Type::Client)
|
||||
continue;
|
||||
|
||||
auto& client_info = thingy.value.get<Client>();
|
||||
if (client_info.output_buffer.empty() || client_info.has_epollout)
|
||||
continue;
|
||||
|
||||
uint32_t events = EPOLLOUT;
|
||||
if (g_server_grabber_fd == -1 || g_server_grabber_fd == client_info.fd)
|
||||
events |= EPOLLIN;
|
||||
|
||||
epoll_event event { .events = events, .data = { .fd = client_info.fd } };
|
||||
if (epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, client_info.fd, &event) == -1)
|
||||
{
|
||||
perror("xbanan: epoll_ctl");
|
||||
close_client(client_info.fd);
|
||||
goto iterator_invalidated;
|
||||
}
|
||||
|
||||
client_info.has_epollout = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user