Display (Linux): merge features of Monitor module

This commit is contained in:
李通洲
2024-09-30 22:43:29 +08:00
parent fb0a18dc82
commit 46eb0e4b1c
10 changed files with 191 additions and 114 deletions
@@ -1,6 +1,5 @@
#include "displayserver_linux.h"
#include "common/io/io.h"
#include "util/edidHelper.h"
#include "util/stringUtils.h"
#ifdef __FreeBSD__
@@ -104,44 +103,6 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
}
}
bool ffdsMatchDrmConnector(const char* connName, FFstrbuf* edidName)
{
// https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_output-event-name
// The doc says that "do not assume that the name is a reflection of an underlying DRM connector, X11 connection, etc."
// However I can't find a better method to get the edid data
const char* drmDirPath = "/sys/class/drm/";
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(drmDirPath);
if(dirp == NULL)
return false;
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
const char* plainName = entry->d_name;
if (ffStrStartsWith(plainName, "card"))
{
const char* tmp = strchr(plainName + strlen("card"), '-');
if (tmp) plainName = tmp + 1;
}
if (ffStrEquals(plainName, connName))
{
ffStrbufAppendF(edidName, "%s%s/edid", drmDirPath, entry->d_name);
uint8_t edidData[128];
if(ffReadFileData(edidName->chars, sizeof(edidData), edidData) == sizeof(edidData))
{
ffStrbufClear(edidName);
ffEdidGetName(edidData, edidName);
return true;
}
break;
}
}
ffStrbufClear(edidName);
return false;
}
FFDisplayType ffdsGetDisplayType(const char* name)
{
if(ffStrStartsWith(name, "eDP-") || ffStrStartsWith(name, "LVDS-"))
@@ -5,8 +5,6 @@
#include "detection/displayserver/displayserver.h"
bool ffdsMatchDrmConnector(const char* connName, FFstrbuf* edidName);
const char* ffdsConnectWayland(FFDisplayServerResult* result);
const char* ffdsConnectXcbRandr(FFDisplayServerResult* result);
+53 -24
View File
@@ -50,15 +50,18 @@ static const char* drmParseSysfs(FFDisplayServerResult* result)
ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength);
ffStrbufAppendS(&drmDir, "/edid");
uint8_t edidData[128];
if(ffReadFileData(drmDir.chars, sizeof(edidData), edidData) == sizeof(edidData))
const char* plainName = entry->d_name;
if (ffStrStartsWith(plainName, "card"))
{
ffEdidGetName(edidData, &name);
ffEdidGetPreferredResolutionAndRefreshRate(edidData, &width, &height, &refreshRate);
ffEdidGetPhysicalSize(edidData, &physicalWidth, &physicalHeight);
const char* tmp = strchr(plainName + strlen("card"), '-');
if (tmp) plainName = tmp + 1;
}
else
uint8_t edidData[512];
ssize_t edidLength = ffReadFileData(drmDir.chars, sizeof(edidData), edidData);
if(edidLength <= 0 || edidLength % 128 != 0)
{
edidLength = 0;
ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength);
ffStrbufAppendS(&drmDir, "/modes");
@@ -66,29 +69,34 @@ static const char* drmParseSysfs(FFDisplayServerResult* result)
if (ffReadFileData(drmDir.chars, sizeof(modes), modes) >= 3)
{
sscanf(modes, "%ux%u", &width, &height);
const char* plainName = entry->d_name;
if (ffStrStartsWith(plainName, "card"))
{
const char* tmp = strchr(plainName + strlen("card"), '-');
if (tmp) plainName = tmp + 1;
}
ffStrbufAppendS(&name, plainName);
}
}
else
{
ffEdidGetName(edidData, &name);
ffEdidGetPreferredResolutionAndRefreshRate(edidData, &width, &height, &refreshRate);
ffEdidGetPhysicalSize(edidData, &physicalWidth, &physicalHeight);
}
ffdsAppendDisplay(
FFDisplayResult* item = ffdsAppendDisplay(
result,
width, height,
refreshRate,
0, 0,
0,
&name,
FF_DISPLAY_TYPE_UNKNOWN,
ffdsGetDisplayType(plainName),
false,
0,
physicalWidth,
physicalHeight
);
if (item && edidLength)
{
item->hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
}
ffStrbufSubstrBefore(&drmDir, drmDirLength);
}
@@ -160,7 +168,7 @@ static inline const char* drmType2Name(uint32_t connector_type)
}
}
static const char* drmGetNameByConnId(uint32_t connId, FFstrbuf* name)
static const char* drmGetEdidByConnId(uint32_t connId, uint8_t* edidData, ssize_t* edidLength)
{
const char* drmDirPath = "/sys/class/drm/";
@@ -182,24 +190,22 @@ static const char* drmGetNameByConnId(uint32_t connId, FFstrbuf* name)
ffStrbufAppendS(&drmDir, entry->d_name);
uint32_t drmDirWithDnameLength = drmDir.length;
char connectorId[16] = {};
ffStrbufAppendS(&drmDir, "/connector_id");
ffReadFileBuffer(drmDir.chars, name);
if (ffStrbufToUInt(name, 0) != connId)
ffReadFileData(drmDir.chars, sizeof(connectorId), connectorId);
if (strtoul(connectorId, NULL, 10) != connId)
{
ffStrbufSubstrBefore(&drmDir, drmDirLength);
continue;
}
ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength);
ffStrbufClear(name);
ffStrbufAppendS(&drmDir, "/edid");
uint8_t edidData[128];
if(ffReadFileData(drmDir.chars, sizeof(edidData), edidData) == sizeof(edidData))
ffEdidGetName(edidData, name);
*edidLength = ffReadFileData(drmDir.chars, (uint32_t) *edidLength, edidData);
return NULL;
}
ffStrbufClear(name);
return "Failed to match connector ID";
}
@@ -309,6 +315,9 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
ffStrbufClear(&name);
uint16_t myear = 0, mweak = 0;
uint32_t serial = 0;
FFDisplayHdrStatus hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN;
for (int iProp = 0; iProp < conn->count_props; ++iProp)
{
@@ -329,7 +338,11 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
if (blob)
{
if (blob->length >= 128)
{
ffEdidGetName(blob->data, &name);
hdrStatus = ffEdidGetHdrCompatible(blob->data, blob->length) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(blob->data, &serial, &myear, &mweak);
}
ffdrmModeFreePropertyBlob(blob);
}
break;
@@ -339,7 +352,15 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
if (name.length == 0)
{
drmGetNameByConnId(conn->connector_id, &name);
uint8_t edidData[512];
ssize_t edidLength = 0;
drmGetEdidByConnId(conn->connector_id, edidData, &edidLength);
if (edidLength > 0 && edidLength % 128 == 0)
{
ffEdidGetName(edidData, &name);
hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(edidData, &serial, &myear, &mweak);
}
}
if (name.length == 0)
@@ -350,7 +371,7 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
ffStrbufSetF(&name, "%s-%d", connectorTypeName, iConn + 1);
}
ffdsAppendDisplay(result,
FFDisplayResult* item = ffdsAppendDisplay(result,
width,
height,
refreshRate,
@@ -367,6 +388,14 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
conn->mmWidth,
conn->mmHeight
);
if (item)
{
item->hdrStatus = hdrStatus;
item->serial = serial;
item->manufactureYear = myear;
item->manufactureWeek = mweak;
}
}
ffdrmModeFreeConnector(conn);
@@ -112,7 +112,7 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist
uint32_t rotation = ffWaylandHandleRotation(&display);
ffdsAppendDisplay(wldata->result,
FFDisplayResult* item = ffdsAppendDisplay(wldata->result,
(uint32_t) display.width,
(uint32_t) display.height,
display.refreshRate / 1000.0,
@@ -131,6 +131,19 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist
(uint32_t) display.physicalWidth,
(uint32_t) display.physicalHeight
);
if (item)
{
if (display.hdrSupported)
item->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED;
else if (display.hdrInfoAvailable)
item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
else
item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN;
item->manufactureYear = display.myear;
item->manufactureWeek = display.mweek;
item->serial = display.serial;
}
ffStrbufDestroy(&display.description);
ffStrbufDestroy(&display.name);
@@ -80,6 +80,9 @@ static void waylandKdeEdidListener(void* data, FF_MAYBE_UNUSED struct kde_output
FF_STRBUF_AUTO_DESTROY edid = ffBase64DecodeStrbuf(&b64);
if (edid.length < 128) return;
ffEdidGetName((const uint8_t*) edid.chars, &wldata->edidName);
wldata->hdrSupported = ffEdidGetHdrCompatible((const uint8_t*) edid.chars, edid.length);
ffEdidGetSerialAndManufactureDate((const uint8_t*) edid.chars, &wldata->serial, &wldata->myear, &wldata->mweek);
wldata->hdrInfoAvailable = true;
}
static void waylandKdeEnabledListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, int32_t enabled)
@@ -195,7 +198,18 @@ void ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry,
);
if (item)
{
item->hdrEnabled = display.hdrEnabled;
if (display.hdrEnabled)
item->hdrStatus = FF_DISPLAY_HDR_STATUS_ENABLED;
else if (display.hdrSupported)
item->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED;
else if (display.hdrInfoAvailable)
item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
else
item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN;
item->manufactureYear = display.myear;
item->manufactureWeek = display.mweek;
item->serial = display.serial;
}
ffStrbufDestroy(&display.description);
@@ -1,5 +1,6 @@
#include "../displayserver_linux.h"
#include "common/io/io.h"
#include "util/edidHelper.h"
#include "util/stringUtils.h"
#include <stdlib.h>
@@ -82,6 +83,46 @@ static void waylandGlobalAddListener(void* data, struct wl_registry* registry, u
}
}
static bool matchDrmConnector(const char* connName, WaylandDisplay* wldata)
{
// https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_output-event-name
// The doc says that "do not assume that the name is a reflection of an underlying DRM connector, X11 connection, etc."
// However I can't find a better method to get the edid data
const char* drmDirPath = "/sys/class/drm/";
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(drmDirPath);
if(dirp == NULL)
return false;
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
const char* plainName = entry->d_name;
if (ffStrStartsWith(plainName, "card"))
{
const char* tmp = strchr(plainName + strlen("card"), '-');
if (tmp) plainName = tmp + 1;
}
if (ffStrEquals(plainName, connName))
{
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateF("%s%s/edid", drmDirPath, entry->d_name);
uint8_t edidData[512];
ssize_t edidLength = ffReadFileData(path.chars, sizeof(edidData), edidData);
if (edidLength <= 0 || edidLength % 128 != 0)
{
ffEdidGetName(edidData, &wldata->edidName);
ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength);
ffEdidGetSerialAndManufactureDate(edidData, &wldata->serial, &wldata->myear, &wldata->mweek);
wldata->hdrInfoAvailable = true;
return true;
}
break;
}
}
return false;
}
void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const char *name)
{
WaylandDisplay* display = data;
@@ -89,7 +130,7 @@ void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const
display->type = ffdsGetDisplayType(name);
if (!display->edidName.length)
ffdsMatchDrmConnector(name, &display->edidName);
matchDrmConnector(name, display);
display->id = ffWaylandGenerateIdFromName(name);
ffStrbufAppendS(&display->name, name);
}
@@ -46,7 +46,12 @@ typedef struct WaylandDisplay
FFstrbuf description;
FFstrbuf edidName;
uint64_t id;
bool hdrInfoAvailable;
bool hdrSupported;
bool hdrEnabled;
uint16_t myear;
uint16_t mweek;
uint32_t serial;
void* internal;
} WaylandDisplay;
@@ -122,7 +122,7 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output
uint32_t rotation = ffWaylandHandleRotation(&display);
ffdsAppendDisplay(wldata->result,
FFDisplayResult* item = ffdsAppendDisplay(wldata->result,
(uint32_t) display.width,
(uint32_t) display.height,
display.refreshRate / 1000.0,
@@ -140,6 +140,19 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output
(uint32_t) display.physicalWidth,
(uint32_t) display.physicalHeight
);
if (item)
{
if (display.hdrSupported)
item->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED;
else if (display.hdrInfoAvailable)
item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
else
item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN;
item->manufactureYear = display.myear;
item->manufactureWeek = display.mweek;
item->serial = display.serial;
}
ffStrbufDestroy(&display.description);
ffStrbufDestroy(&display.name);
+27 -34
View File
@@ -180,47 +180,29 @@ typedef struct XcbRandrData
xcb_randr_get_screen_resources_current_reply_t* screenResources;
} XcbRandrData;
static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* modeInfo, FFstrbuf* name, uint32_t rotation, bool primary, xcb_randr_get_output_info_reply_t* output, FFDisplayType displayType)
{
double refreshRate = (double) modeInfo->dot_clock / (double) (modeInfo->htotal * modeInfo->vtotal);
return ffdsAppendDisplay(
data->result,
(uint32_t) modeInfo->width,
(uint32_t) modeInfo->height,
refreshRate,
(uint32_t) modeInfo->width,
(uint32_t) modeInfo->height,
rotation,
name,
displayType,
primary,
0,
(uint32_t) output->mm_width,
(uint32_t) output->mm_height
);
}
static bool xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode, FFstrbuf* name, uint32_t rotation, bool primary, xcb_randr_get_output_info_reply_t* output, FFDisplayType displayType)
static double xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode)
{
//We do the check here, because we want the best fallback display if this call failed
if(data->screenResources == NULL)
return false;
return 0;
xcb_randr_mode_info_iterator_t modesIterator = data->ffxcb_randr_get_screen_resources_current_modes_iterator(data->screenResources);
while(modesIterator.rem > 0)
{
if(modesIterator.data->id == mode)
return xcbRandrHandleModeInfo(data, modesIterator.data, name, rotation, primary, output, displayType);
{
xcb_randr_mode_info_t* modeInfo = modesIterator.data;
return (double) modeInfo->dot_clock / (double) (modeInfo->htotal * modeInfo->vtotal);
}
data->ffxcb_randr_mode_info_next(&modesIterator);
}
return false;
return 0;
}
static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrbuf* name, bool primary, xcb_randr_get_output_info_reply_t* output, FFDisplayType displayType)
static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrbuf* name, bool primary, xcb_randr_get_output_info_reply_t* output, FFDisplayType displayType, uint8_t* edidData, uint32_t edidLength)
{
xcb_randr_get_crtc_info_cookie_t crtcInfoCookie = data->ffxcb_randr_get_crtc_info(data->connection, crtc, XCB_CURRENT_TIME);
FF_AUTO_FREE xcb_randr_get_crtc_info_reply_t* crtcInfoReply = data->ffxcb_randr_get_crtc_info_reply(data->connection, crtcInfoCookie, NULL);
@@ -243,12 +225,12 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrb
rotation = 0;
break;
}
bool res = xcbRandrHandleMode(data, crtcInfoReply->mode, name, rotation, primary, output, displayType);
res = res ? true : !!ffdsAppendDisplay(
FFDisplayResult* item = ffdsAppendDisplay(
data->result,
(uint32_t) crtcInfoReply->width,
(uint32_t) crtcInfoReply->height,
0,
xcbRandrHandleMode(data, crtcInfoReply->mode),
(uint32_t) crtcInfoReply->width,
(uint32_t) crtcInfoReply->height,
rotation,
@@ -259,8 +241,13 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrb
(uint32_t) output->mm_width,
(uint32_t) output->mm_height
);
if (item && edidLength)
{
item->hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
}
return res;
return !!item;
}
static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output, FFstrbuf* name, bool primary, FFDisplayType displayType)
@@ -272,21 +259,27 @@ static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output,
xcb_intern_atom_cookie_t requestAtomCookie = data->ffxcb_intern_atom(data->connection, true, (uint16_t) strlen("EDID"), "EDID");
FF_AUTO_FREE xcb_intern_atom_reply_t* requestAtomReply = data->ffxcb_intern_atom_reply(data->connection, requestAtomCookie, NULL);
FF_AUTO_FREE xcb_randr_get_output_property_reply_t* outputPropertyReply = NULL;
uint8_t* edidData = NULL;
uint32_t edidLength = 0;
if(requestAtomReply)
{
xcb_randr_get_output_property_cookie_t outputPropertyCookie = data->ffxcb_randr_get_output_property(data->connection, output, requestAtomReply->atom, XCB_GET_PROPERTY_TYPE_ANY, 0, 100, false, false);
FF_AUTO_FREE xcb_randr_get_output_property_reply_t* outputPropertyReply = data->ffxcb_randr_get_output_property_reply(data->connection, outputPropertyCookie, NULL);
outputPropertyReply = data->ffxcb_randr_get_output_property_reply(data->connection, outputPropertyCookie, NULL);
if(outputPropertyReply)
{
if(data->ffxcb_randr_get_output_property_data_length(outputPropertyReply) >= 128)
int len = data->ffxcb_randr_get_output_property_data_length(outputPropertyReply);
if(len >= 128)
{
ffStrbufClear(name);
ffEdidGetName(data->ffxcb_randr_get_output_property_data(outputPropertyReply), name);
edidData = data->ffxcb_randr_get_output_property_data(outputPropertyReply);
ffEdidGetName(edidData, name);
edidLength = (uint32_t) len;
}
}
}
bool res = xcbRandrHandleCrtc(data, outputInfoReply->crtc, name, primary, outputInfoReply, displayType);
bool res = xcbRandrHandleCrtc(data, outputInfoReply->crtc, name, primary, outputInfoReply, displayType, edidData, edidLength);
return res;
}
+21 -11
View File
@@ -153,13 +153,13 @@ static double xrandrHandleMode(XrandrData* data, RRMode mode)
return 0;
}
static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc, FFstrbuf* name, bool primary, XRROutputInfo* output, FFDisplayType displayType)
static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf* name, bool primary, FFDisplayType displayType, uint8_t* edidData, uint32_t edidLength)
{
//We do the check here, because we want the best fallback display if this call failed
if(data->screenResources == NULL)
return false;
XRRCrtcInfo* crtcInfo = data->ffXRRGetCrtcInfo(data->display, data->screenResources, crtc);
XRRCrtcInfo* crtcInfo = data->ffXRRGetCrtcInfo(data->display, data->screenResources, output->crtc);
if(crtcInfo == NULL)
return false;
@@ -180,7 +180,7 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc, FFstrbuf* name, bool
break;
}
bool res = ffdsAppendDisplay(
FFDisplayResult* item = ffdsAppendDisplay(
data->result,
(uint32_t) crtcInfo->width,
(uint32_t) crtcInfo->height,
@@ -196,8 +196,14 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc, FFstrbuf* name, bool
(uint32_t) output->mm_height
);
if (edidLength)
{
item->hdrStatus = ffEdidGetHdrCompatible(edidData, edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
}
data->ffXRRFreeCrtcInfo(crtcInfo);
return res;
return !!item;
}
static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name, bool primary, FFDisplayType displayType)
@@ -206,26 +212,30 @@ static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name
if(outputInfo == NULL)
return false;
uint8_t* edidData = NULL;
unsigned long edidLength = 0;
Atom atomEdid = data->ffXInternAtom(data->display, "EDID", true);
if (atomEdid != None)
{
int actual_format = 0;
unsigned long nitems = 0, bytes_after = 0;
unsigned long bytes_after = 0;
Atom actual_type = None;
uint8_t* edidData = NULL;
if (data->ffXRRGetOutputProperty(data->display, output, atomEdid, 0, 100, false, false, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &edidData) == Success)
if (data->ffXRRGetOutputProperty(data->display, output, atomEdid, 0, 100, false, false, AnyPropertyType, &actual_type, &actual_format, &edidLength, &bytes_after, &edidData) == Success)
{
if (nitems >= 128)
if (edidLength >= 128)
{
ffStrbufClear(name);
ffEdidGetName(edidData, name);
}
else
edidLength = 0;
}
if (edidData)
data->ffXFree(edidData);
}
bool res = xrandrHandleCrtc(data, outputInfo->crtc, name, primary, outputInfo, displayType);
bool res = xrandrHandleCrtc(data, outputInfo, name, primary, displayType, edidData, (uint32_t) edidLength);
if (edidData)
data->ffXFree(edidData);
data->ffXRRFreeOutputInfo(outputInfo);
return res;