Make RANDR report multiple monitors correctly

This fixes broken aspect ratio in Celeste when running fullscreen
This commit is contained in:
2026-06-05 01:04:30 +03:00
parent a6a581347e
commit 0e0624ceb6
7 changed files with 306 additions and 203 deletions

View File

@@ -159,6 +159,16 @@ static const char* s_opcode_to_name[] {
[X_NoOperation] = "X_NoOperation", [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 Object::Window::full_event_mask() const
{ {
uint32_t full_event_mask = 0; uint32_t full_event_mask = 0;
@@ -200,9 +210,9 @@ BAN::ErrorOr<void> setup_client_conneciton(Client& client_info, const xConnClien
xConnSetupPrefix setup_prefix { xConnSetupPrefix setup_prefix {
.success = 1, .success = 1,
.lengthReason = 0, // wtf is this .lengthReason = 0, // wtf is this
.majorVersion = client_prefix.majorVersion, .majorVersion = 11,
.minorVersion = client_prefix.minorVersion, .minorVersion = 0,
.length = 8 + 2*format_count + (8 + 0 + sz_xWindowRoot + sz_xDepth + sz_xVisualType) / 4, .length = 8 + 2 * format_count + (8 + 0 + sz_xWindowRoot + sz_xDepth + sz_xVisualType) / 4,
}; };
TRY(encode(client_info.output_buffer, setup_prefix)); TRY(encode(client_info.output_buffer, setup_prefix));
@@ -1363,15 +1373,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
CARD16 width, height; CARD16 width, height;
CARD8 depth; CARD8 depth;
if (drawable_id == g_root.windowId) if (drawable.type == Object::Type::Window)
{
width = g_root.pixWidth;
height = g_root.pixHeight;
depth = g_root.rootDepth;
x = 0;
y = 0;
}
else if (drawable.type == Object::Type::Window)
{ {
const auto& window = drawable.object.get<Object::Window>(); const auto& window = drawable.object.get<Object::Window>();
width = window.width; width = window.width;

View File

@@ -161,6 +161,12 @@ struct EpollThingy
BAN::Variant<Client, void*> value; BAN::Variant<Client, void*> value;
}; };
struct DisplayInfo
{
int32_t x, y;
uint32_t w, h;
};
extern const xPixmapFormat g_formats[6]; extern const xPixmapFormat g_formats[6];
extern const xDepth g_depth; extern const xDepth g_depth;
extern const xVisualType g_visual; extern const xVisualType g_visual;
@@ -176,3 +182,7 @@ extern int g_epoll_fd;
extern BAN::HashMap<int, EpollThingy> g_epoll_thingies; extern BAN::HashMap<int, EpollThingy> g_epoll_thingies;
extern int g_server_grabber_fd; extern int g_server_grabber_fd;
extern BAN::Vector<DisplayInfo> g_displays;
extern CARD32 g_next_global_id;

View File

@@ -6,12 +6,64 @@
#include <time.h> #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 BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpan packet)
{ {
static CARD32 crtc_id = 5; if (s_randr_displays.empty())
static CARD32 output_id = 6; initialize_displays();
static CARD32 mode_id = 7;
static CARD32 timestamp = time(nullptr);
static xRenderTransform transform { static xRenderTransform transform {
1 << 16, 0, 0, 1 << 16, 0, 0,
@@ -62,8 +114,8 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
.sequenceNumber = client_info.sequence, .sequenceNumber = client_info.sequence,
.length = 3, .length = 3,
.root = g_root.windowId, .root = g_root.windowId,
.timestamp = timestamp, .timestamp = s_timestamp,
.configTimestamp = timestamp, .configTimestamp = s_timestamp,
.nSizes = 1, .nSizes = 1,
.sizeID = 0, .sizeID = 0,
.rotation = RR_Rotate_0, .rotation = RR_Rotate_0,
@@ -115,39 +167,45 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
dprintln("RRGetScreenResources{}", current ? "Current" : ""); dprintln("RRGetScreenResources{}", current ? "Current" : "");
dprintln(" window: {}", request.window); 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 { xRRGetScreenResourcesReply reply {
.type = X_Reply, .type = X_Reply,
.sequenceNumber = client_info.sequence, .sequenceNumber = client_info.sequence,
.length = static_cast<CARD32>(1 + 1 + 8 + (mode_name.size() + 3) / 4), .length = static_cast<CARD32>(s_randr_displays.size() * (1 + 1 + 8) + (mode_name_bytes + 3) / 4),
.timestamp = timestamp, .timestamp = s_timestamp,
.configTimestamp = timestamp, .configTimestamp = s_timestamp,
.nCrtcs = 1, .nCrtcs = static_cast<CARD16>(s_randr_displays.size()),
.nOutputs = 1, .nOutputs = static_cast<CARD16>(s_randr_displays.size()),
.nModes = 1, .nModes = static_cast<CARD16>(s_randr_displays.size()),
.nbytesNames = static_cast<CARD16>(mode_name.size()), .nbytesNames = static_cast<CARD16>(mode_name_bytes),
}; };
TRY(encode(client_info.output_buffer, reply)); 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; for (const auto& display : s_randr_displays)
const CARD16 hsync_end = g_root.pixWidth + 1; {
const CARD16 htotal = g_root.pixWidth + 1; 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_start = display.info.h;
const CARD16 vsync_end = g_root.pixHeight + 1; const CARD16 vsync_end = display.info.h + 1;
const CARD16 vtotal = g_root.pixHeight + 1; const CARD16 vtotal = display.info.h + 1;
const CARD32 clock = htotal * vtotal * 60; const CARD32 clock = htotal * vtotal * 60;
xRRModeInfo mode_info { xRRModeInfo mode_info {
.id = mode_id, .id = display.mode_id,
.width = g_root.pixWidth, .width = static_cast<CARD16>(display.info.w),
.height = g_root.pixHeight, .height = static_cast<CARD16>(display.info.h),
.dotClock = clock, .dotClock = clock,
.hSyncStart = hsync_start, .hSyncStart = hsync_start,
.hSyncEnd = hsync_end, .hSyncEnd = hsync_end,
@@ -156,14 +214,16 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
.vSyncStart = vsync_start, .vSyncStart = vsync_start,
.vSyncEnd = vsync_end, .vSyncEnd = vsync_end,
.vTotal = vtotal, .vTotal = vtotal,
.nameLength = static_cast<CARD16>(mode_name.size()), .nameLength = static_cast<CARD16>(display.mode_str.size()),
.modeFlags = RR_HSyncPositive | RR_VSyncPositive, .modeFlags = RR_HSyncPositive | RR_VSyncPositive,
}; };
TRY(encode(client_info.output_buffer, mode_info)); TRY(encode(client_info.output_buffer, mode_info));
}
TRY(encode(client_info.output_buffer, mode_name)); for (const auto& display : s_randr_displays)
for (size_t i = 0; (mode_name.size() + i) % 4; i++) TRY(encode(client_info.output_buffer, display.mode_str));
TRY(encode(client_info.output_buffer, '\0')); while (client_info.output_buffer.size() % 4)
TRY(encode<BYTE>(client_info.output_buffer, 0));
break; break;
} }
@@ -175,27 +235,31 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
dprintln(" output: {}", request.output); dprintln(" output: {}", request.output);
dprintln(" configTimestamp: {}", request.configTimestamp); dprintln(" configTimestamp: {}", request.configTimestamp);
const auto& display = find_display_by_output(request.output);
xRRGetOutputInfoReply reply { xRRGetOutputInfoReply reply {
.type = X_Reply, .type = X_Reply,
.status = Success, .status = Success,
.sequenceNumber = client_info.sequence, .sequenceNumber = client_info.sequence,
.length = 1 + 1 + 1 + 2, .length = static_cast<CARD32>(1 + 1 + 1 + (display.output_str.size() + 3) / 4),
.timestamp = timestamp, .timestamp = s_timestamp,
.crtc = crtc_id, .crtc = display.crtc_id,
.mmWidth = g_root.mmWidth, .mmWidth = display.info.w * 254 / 960, // 96 DPI
.mmHeight = g_root.mmHeight, .mmHeight = display.info.h * 254 / 960, // 96 DPI
.connection = RR_Connected, .connection = RR_Connected,
.subpixelOrder = SubPixelUnknown, .subpixelOrder = SubPixelUnknown,
.nCrtcs = 1, .nCrtcs = 1,
.nModes = 1, .nModes = 1,
.nPreferred = 1, .nPreferred = 1,
.nClones = 0, .nClones = 0,
.nameLength = 5, .nameLength = static_cast<CARD16>(display.output_str.size()),
}; };
TRY(encode(client_info.output_buffer, reply)); TRY(encode(client_info.output_buffer, reply));
TRY(encode(client_info.output_buffer, crtc_id)); TRY(encode(client_info.output_buffer, display.crtc_id));
TRY(encode(client_info.output_buffer, mode_id)); TRY(encode(client_info.output_buffer, display.mode_id));
TRY(encode(client_info.output_buffer, "B-OUT\0\0\0"_sv)); 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; break;
} }
@@ -250,25 +314,27 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
dprintln(" crtc: {}", request.crtc); dprintln(" crtc: {}", request.crtc);
dprintln(" configTimestamp: {}", request.configTimestamp); dprintln(" configTimestamp: {}", request.configTimestamp);
const auto& display = find_display_by_crtc(request.crtc);
xRRGetCrtcInfoReply reply { xRRGetCrtcInfoReply reply {
.type = X_Reply, .type = X_Reply,
.status = Success, .status = Success,
.sequenceNumber = client_info.sequence, .sequenceNumber = client_info.sequence,
.length = 2, .length = 2,
.timestamp = timestamp, .timestamp = s_timestamp,
.x = 0, .x = static_cast<INT16>(display.info.x),
.y = 0, .y = static_cast<INT16>(display.info.y),
.width = g_root.pixWidth, .width = static_cast<CARD16>(display.info.w),
.height = g_root.pixHeight, .height = static_cast<CARD16>(display.info.h),
.mode = mode_id, .mode = display.mode_id,
.rotation = RR_Rotate_0, .rotation = RR_Rotate_0,
.rotations = RR_Rotate_0, .rotations = RR_Rotate_0,
.nOutput = 1, .nOutput = 1,
.nPossibleOutput = 1, .nPossibleOutput = 1,
}; };
TRY(encode(client_info.output_buffer, reply)); TRY(encode(client_info.output_buffer, reply));
TRY(encode(client_info.output_buffer, output_id)); TRY(encode(client_info.output_buffer, display.output_id));
TRY(encode(client_info.output_buffer, output_id)); TRY(encode(client_info.output_buffer, display.output_id));
break; break;
} }
@@ -285,13 +351,13 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
dprintln(" mode: {}", request.mode); dprintln(" mode: {}", request.mode);
dprintln(" rotation: {}", request.rotation); dprintln(" rotation: {}", request.rotation);
timestamp = time(nullptr); s_timestamp = time(nullptr);
xRRSetCrtcConfigReply reply { xRRSetCrtcConfigReply reply {
.type = X_Reply, .type = X_Reply,
.status = Success, .status = Success,
.sequenceNumber = client_info.sequence, .sequenceNumber = client_info.sequence,
.length = 0, .length = 0,
.newTimestamp = timestamp, .newTimestamp = s_timestamp,
}; };
TRY(encode(client_info.output_buffer, reply)); 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(); auto request = decode<xRRGetCrtcGammaSizeReq>(packet).value();
dprintln("RRGetCrtcGammaSize"); dwarnln("RRGetCrtcGammaSize");
dprintln(" crtc: {}", request.crtc); dwarnln(" crtc: {}", request.crtc);
xRRGetCrtcGammaSizeReply reply { xRRGetCrtcGammaSizeReply reply {
.type = X_Reply, .type = X_Reply,
.status = Success, .status = Success,
.sequenceNumber = client_info.sequence, .sequenceNumber = client_info.sequence,
.length = 0, .length = 0,
.size = 1, .size = 256,
}; };
TRY(encode(client_info.output_buffer, reply)); TRY(encode(client_info.output_buffer, reply));
@@ -326,14 +392,13 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
.type = X_Reply, .type = X_Reply,
.status = Success, .status = Success,
.sequenceNumber = client_info.sequence, .sequenceNumber = client_info.sequence,
.length = 2, .length = (6 * 256) / 4,
.size = 1, .size = 256,
}; };
TRY(encode(client_info.output_buffer, reply)); TRY(encode(client_info.output_buffer, reply));
TRY(encode<CARD16>(client_info.output_buffer, 1)); for (size_t i = 0; i < 3; i++)
TRY(encode<CARD16>(client_info.output_buffer, 1)); for (size_t j = 0; j < 256; j++)
TRY(encode<CARD16>(client_info.output_buffer, 1)); TRY(encode<CARD16>(client_info.output_buffer, j * 65535 / 255));
TRY(encode<CARD16>(client_info.output_buffer, 0));
break; break;
} }
@@ -373,7 +438,7 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
.status = Success, .status = Success,
.sequenceNumber = client_info.sequence, .sequenceNumber = client_info.sequence,
.length = 1, .length = 1,
.timestamp = timestamp, .timestamp = s_timestamp,
.left = 0, .left = 0,
.top = 0, .top = 0,
.width = 0, .width = 0,
@@ -402,7 +467,7 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
.type = X_Reply, .type = X_Reply,
.sequenceNumber = client_info.sequence, .sequenceNumber = client_info.sequence,
.length = 0, .length = 0,
.output = output_id, .output = s_randr_displays.front().output_id,
}; };
TRY(encode(client_info.output_buffer, reply)); TRY(encode(client_info.output_buffer, reply));
@@ -419,7 +484,7 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
.type = X_Reply, .type = X_Reply,
.sequenceNumber = client_info.sequence, .sequenceNumber = client_info.sequence,
.length = 0, .length = 0,
.timestamp = timestamp, .timestamp = s_timestamp,
.nProviders = 0, .nProviders = 0,
}; };
TRY(encode(client_info.output_buffer, reply)); TRY(encode(client_info.output_buffer, reply));
@@ -438,28 +503,30 @@ static BAN::ErrorOr<void> extension_randr(Client& client_info, BAN::ConstByteSpa
.type = X_Reply, .type = X_Reply,
.status = Success, .status = Success,
.sequenceNumber = client_info.sequence, .sequenceNumber = client_info.sequence,
.length = 6 + 1, .length = static_cast<CARD32>(6 * s_randr_displays.size() + s_randr_displays.size()),
.timestamp = timestamp, .timestamp = s_timestamp,
.nmonitors = 1, .nmonitors = static_cast<CARD32>(s_randr_displays.size()),
.noutputs = 1, .noutputs = static_cast<CARD32>(s_randr_displays.size()),
}; };
TRY(encode(client_info.output_buffer, reply)); TRY(encode(client_info.output_buffer, reply));
for (const auto& display : s_randr_displays)
{
xRRMonitorInfo monitor { xRRMonitorInfo monitor {
.name = None, .name = display.name_atom,
.primary = xTrue, .primary = (&display == &s_randr_displays.front()),
.automatic = xTrue, .automatic = xTrue,
.noutput = 1, .noutput = 1,
.x = 0, .x = static_cast<INT16>(display.info.x),
.y = 0, .y = static_cast<INT16>(display.info.y),
.width = g_root.pixWidth, .width = static_cast<CARD16>(display.info.w),
.height = g_root.pixHeight, .height = static_cast<CARD16>(display.info.h),
.widthInMillimeters = g_root.mmWidth, .widthInMillimeters = display.info.w * 254 / 96, // 96 DPI
.heightInMillimeters = g_root.mmHeight, .heightInMillimeters = display.info.h * 254 / 96, // 96 DPI
}; };
TRY(encode(client_info.output_buffer, monitor)); TRY(encode(client_info.output_buffer, monitor));
TRY(encode(client_info.output_buffer, display.output_id));
TRY(encode(client_info.output_buffer, output_id)); }
break; break;
} }

View File

@@ -47,7 +47,7 @@ enum class SystemCursorType
struct PlatformOps struct PlatformOps
{ {
/* Do platform initialization */ /* Do platform initialization */
bool (*initialize)(uint32_t* width, uint32_t* height); bool (*initialize)();
/* Handle pending events */ /* Handle pending events */
void (*poll_events)(void*); void (*poll_events)(void*);
/* Create a window with given size */ /* Create a window with given size */
@@ -74,3 +74,5 @@ struct PlatformOps
void (*set_cursor)(PlatformWindow*, PlatformCursor*); void (*set_cursor)(PlatformWindow*, PlatformCursor*);
}; };
extern PlatformOps g_platform_ops; extern PlatformOps g_platform_ops;
void register_display(int32_t x, int32_t y, uint32_t width, uint32_t height);

View File

@@ -69,7 +69,7 @@ static void* sdl3_thread(void*)
static void sdl3_initialize_keymap(); 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)) 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; return false;
} }
*display_w = *display_h = 0;
const SDL_DisplayID* display_ids = SDL_GetDisplays(nullptr); const SDL_DisplayID* display_ids = SDL_GetDisplays(nullptr);
for (int i = 0; display_ids[i]; i++) for (int i = 0; display_ids[i]; i++)
{ {
SDL_Rect rect; SDL_Rect rect;
SDL_GetDisplayBounds(display_ids[i], &rect); if (!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); dwarnln("Could not display {} bounds: {}", SDL_GetError());
continue;
}
register_display(rect.x, rect.y, rect.w, rect.h);
} }
sdl3_initialize_keymap(); sdl3_initialize_keymap();

View File

@@ -28,7 +28,7 @@ struct BananCursor final : public PlatformCursor
static BAN::ErrorOr<void> bananos_initialize_keymap(); 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; auto attributes = LibGUI::Window::default_attributes;
attributes.shown = false; attributes.shown = false;
@@ -40,8 +40,7 @@ static bool bananos_initialize(uint32_t* display_w, uint32_t* display_h)
return false; return false;
} }
*display_w = dummy_or_error.value()->width(); register_display(0, 0, dummy_or_error.value()->width(), dummy_or_error.value()->height());
*display_h = dummy_or_error.value()->height();
if (auto ret = bananos_initialize_keymap(); ret.is_error()) if (auto ret = bananos_initialize_keymap(); ret.is_error())
{ {

View File

@@ -19,6 +19,8 @@
#include <netinet/in.h> #include <netinet/in.h>
#endif #endif
CARD32 g_next_global_id { 1 };
const xPixmapFormat g_formats[6] { const xPixmapFormat g_formats[6] {
{ {
.depth = 1, .depth = 1,
@@ -58,7 +60,7 @@ const xDepth g_depth {
}; };
const xVisualType g_visual { const xVisualType g_visual {
.visualID = 1, .visualID = g_next_global_id++,
.c_class = TrueColor, .c_class = TrueColor,
.bitsPerRGB = 8, .bitsPerRGB = 8,
.colormapEntries = 256, .colormapEntries = 256,
@@ -68,7 +70,7 @@ const xVisualType g_visual {
}; };
xWindowRoot g_root { xWindowRoot g_root {
.windowId = 2, .windowId = g_next_global_id++,
.defaultColormap = 0, .defaultColormap = 0,
.whitePixel = 0xFFFFFF, .whitePixel = 0xFFFFFF,
.blackPixel = 0x000000, .blackPixel = 0x000000,
@@ -82,10 +84,12 @@ xWindowRoot g_root {
.rootVisualID = g_visual.visualID, .rootVisualID = g_visual.visualID,
.backingStore = 0, .backingStore = 0,
.saveUnders = 0, .saveUnders = 0,
.rootDepth = 24, .rootDepth = g_depth.depth,
.nDepths = 1, .nDepths = 1,
}; };
BAN::Vector<DisplayInfo> g_displays;
BAN::HashMap<CARD32, BAN::UniqPtr<Object>> g_objects; BAN::HashMap<CARD32, BAN::UniqPtr<Object>> g_objects;
BAN::HashMap<BAN::String, ATOM> g_atoms_name_to_id; BAN::HashMap<BAN::String, ATOM> g_atoms_name_to_id;
@@ -261,13 +265,53 @@ int main()
APPEND_ATOM_CUSTOM(_NET_WM_WINDOW_TYPE_UTILITY); APPEND_ATOM_CUSTOM(_NET_WM_WINDOW_TYPE_UTILITY);
#undef APPEND_ATOM_CUSTOM #undef APPEND_ATOM_CUSTOM
uint32_t display_w, display_h; if (!g_platform_ops.initialize())
if (!g_platform_ops.initialize(&display_w, &display_h))
return 1; return 1;
g_root.pixWidth = display_w;
g_root.pixHeight = display_h; if (g_displays.empty())
g_root.mmWidth = static_cast<CARD16>(display_w * 254 / 960); // 96 DPI {
g_root.mmHeight = static_cast<CARD16>(display_h * 254 / 960); // 96 DPI 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"); printf("xbanan started\n");
@@ -353,28 +397,6 @@ int main()
} }
}; };
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,
}
}))
));
MUST(g_objects.insert(g_visual.visualID,
MUST(BAN::UniqPtr<Object>::create(Object {
.type = Object::Type::Visual,
}))
));
for (;;) for (;;)
{ {
epoll_event events[16]; epoll_event events[16];