3
3
#ifdef FF_HAVE_XCB_RANDR
4
4
5
5
#include "common/library.h"
6
- #include "common/time .h"
6
+ #include "common/properties .h"
7
7
#include "util/edidHelper.h"
8
8
#include "util/mallocHelper.h"
9
9
#include "util/stringUtils.h"
@@ -56,7 +56,7 @@ static void* xcbGetProperty(XcbPropertyData* data, xcb_connection_t* connection,
56
56
if (requestAtomReply == NULL )
57
57
return NULL ;
58
58
59
- xcb_get_property_cookie_t propertyCookie = data -> ffxcb_get_property (connection , false, window , requestAtomReply -> atom , XCB_ATOM_ANY , 0 , 64 );
59
+ xcb_get_property_cookie_t propertyCookie = data -> ffxcb_get_property (connection , false, window , requestAtomReply -> atom , XCB_ATOM_ANY , 0 , 8 * 1024 );
60
60
61
61
FF_AUTO_FREE xcb_get_property_reply_t * propertyReply = data -> ffxcb_get_property_reply (connection , propertyCookie , NULL );
62
62
if (propertyReply == NULL )
@@ -138,14 +138,38 @@ typedef struct XcbRandrData
138
138
xcb_connection_t * connection ;
139
139
FFDisplayServerResult * result ;
140
140
XcbPropertyData propData ;
141
-
142
- //init per screen
143
- xcb_randr_get_screen_resources_current_reply_t * screenResources ;
144
141
} XcbRandrData ;
145
142
146
- 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 )
143
+ static bool xcbRandrHandleOutput (XcbRandrData * data , xcb_randr_output_t output , FFstrbuf * name , bool primary , FFDisplayType displayType , struct xcb_randr_get_screen_resources_current_reply_t * screenResources , uint8_t bitDepth , double scaleFactor )
147
144
{
148
- xcb_randr_get_crtc_info_cookie_t crtcInfoCookie = data -> ffxcb_randr_get_crtc_info (data -> connection , crtc , XCB_CURRENT_TIME );
145
+ xcb_randr_get_output_info_cookie_t outputInfoCookie = data -> ffxcb_randr_get_output_info (data -> connection , output , XCB_CURRENT_TIME );
146
+ FF_AUTO_FREE xcb_randr_get_output_info_reply_t * outputInfoReply = data -> ffxcb_randr_get_output_info_reply (data -> connection , outputInfoCookie , NULL );
147
+ if (outputInfoReply == NULL )
148
+ return false;
149
+
150
+ xcb_intern_atom_cookie_t requestAtomCookie = data -> ffxcb_intern_atom (data -> connection , true, (uint16_t ) strlen ("EDID" ), "EDID" );
151
+ FF_AUTO_FREE xcb_intern_atom_reply_t * requestAtomReply = data -> ffxcb_intern_atom_reply (data -> connection , requestAtomCookie , NULL );
152
+ FF_AUTO_FREE xcb_randr_get_output_property_reply_t * outputPropertyReply = NULL ;
153
+ uint8_t * edidData = NULL ;
154
+ uint32_t edidLength = 0 ;
155
+ if (requestAtomReply )
156
+ {
157
+ 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);
158
+ outputPropertyReply = data -> ffxcb_randr_get_output_property_reply (data -> connection , outputPropertyCookie , NULL );
159
+ if (outputPropertyReply )
160
+ {
161
+ int len = data -> ffxcb_randr_get_output_property_data_length (outputPropertyReply );
162
+ if (len >= 128 )
163
+ {
164
+ ffStrbufClear (name );
165
+ edidData = data -> ffxcb_randr_get_output_property_data (outputPropertyReply );
166
+ ffEdidGetName (edidData , name );
167
+ edidLength = (uint32_t ) len ;
168
+ }
169
+ }
170
+ }
171
+
172
+ xcb_randr_get_crtc_info_cookie_t crtcInfoCookie = data -> ffxcb_randr_get_crtc_info (data -> connection , outputInfoReply -> crtc , XCB_CURRENT_TIME );
149
173
FF_AUTO_FREE xcb_randr_get_crtc_info_reply_t * crtcInfoReply = data -> ffxcb_randr_get_crtc_info_reply (data -> connection , crtcInfoCookie , NULL );
150
174
if (crtcInfoReply == NULL )
151
175
return false;
@@ -170,11 +194,11 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrb
170
194
xcb_randr_mode_info_t * currentMode = NULL ;
171
195
xcb_randr_mode_info_t * preferredMode = NULL ;
172
196
173
- if (data -> screenResources )
197
+ if (screenResources )
174
198
{
175
- xcb_randr_mode_info_iterator_t modesIterator = data -> ffxcb_randr_get_screen_resources_current_modes_iterator (data -> screenResources );
199
+ xcb_randr_mode_info_iterator_t modesIterator = data -> ffxcb_randr_get_screen_resources_current_modes_iterator (screenResources );
176
200
177
- if (output -> num_preferred > 0 )
201
+ if (outputInfoReply -> num_preferred > 0 )
178
202
preferredMode = modesIterator .data ;
179
203
180
204
while (modesIterator .rem > 0 )
@@ -194,8 +218,8 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrb
194
218
(uint32_t ) crtcInfoReply -> width ,
195
219
(uint32_t ) crtcInfoReply -> height ,
196
220
currentMode ? (double ) currentMode -> dot_clock / (double ) ((uint32_t ) currentMode -> htotal * currentMode -> vtotal ) : 0 ,
197
- (uint32_t ) crtcInfoReply -> width ,
198
- (uint32_t ) crtcInfoReply -> height ,
221
+ (uint32_t ) ( crtcInfoReply -> width / scaleFactor + .5 ) ,
222
+ (uint32_t ) ( crtcInfoReply -> height / scaleFactor + .5 ) ,
199
223
preferredMode ? (uint32_t ) preferredMode -> width : 0 ,
200
224
preferredMode ? (uint32_t ) preferredMode -> height : 0 ,
201
225
preferredMode ? (double ) preferredMode -> dot_clock / (double ) ((uint32_t ) preferredMode -> htotal * preferredMode -> vtotal ) : 0 ,
@@ -204,54 +228,21 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrb
204
228
displayType ,
205
229
primary ,
206
230
0 ,
207
- (uint32_t ) output -> mm_width ,
208
- (uint32_t ) output -> mm_height ,
231
+ (uint32_t ) outputInfoReply -> mm_width ,
232
+ (uint32_t ) outputInfoReply -> mm_height ,
209
233
"xcb-randr-crtc"
210
234
);
211
235
if (item && edidLength )
212
236
{
213
237
item -> hdrStatus = ffEdidGetHdrCompatible (edidData , (uint32_t ) edidLength ) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED ;
214
238
ffEdidGetSerialAndManufactureDate (edidData , & item -> serial , & item -> manufactureYear , & item -> manufactureWeek );
239
+ item -> bitDepth = bitDepth ;
215
240
}
216
241
217
242
return !!item ;
218
243
}
219
244
220
- static bool xcbRandrHandleOutput (XcbRandrData * data , xcb_randr_output_t output , FFstrbuf * name , bool primary , FFDisplayType displayType )
221
- {
222
- xcb_randr_get_output_info_cookie_t outputInfoCookie = data -> ffxcb_randr_get_output_info (data -> connection , output , XCB_CURRENT_TIME );
223
- FF_AUTO_FREE xcb_randr_get_output_info_reply_t * outputInfoReply = data -> ffxcb_randr_get_output_info_reply (data -> connection , outputInfoCookie , NULL );
224
- if (outputInfoReply == NULL )
225
- return false;
226
-
227
- xcb_intern_atom_cookie_t requestAtomCookie = data -> ffxcb_intern_atom (data -> connection , true, (uint16_t ) strlen ("EDID" ), "EDID" );
228
- FF_AUTO_FREE xcb_intern_atom_reply_t * requestAtomReply = data -> ffxcb_intern_atom_reply (data -> connection , requestAtomCookie , NULL );
229
- FF_AUTO_FREE xcb_randr_get_output_property_reply_t * outputPropertyReply = NULL ;
230
- uint8_t * edidData = NULL ;
231
- uint32_t edidLength = 0 ;
232
- if (requestAtomReply )
233
- {
234
- 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);
235
- outputPropertyReply = data -> ffxcb_randr_get_output_property_reply (data -> connection , outputPropertyCookie , NULL );
236
- if (outputPropertyReply )
237
- {
238
- int len = data -> ffxcb_randr_get_output_property_data_length (outputPropertyReply );
239
- if (len >= 128 )
240
- {
241
- ffStrbufClear (name );
242
- edidData = data -> ffxcb_randr_get_output_property_data (outputPropertyReply );
243
- ffEdidGetName (edidData , name );
244
- edidLength = (uint32_t ) len ;
245
- }
246
- }
247
- }
248
-
249
- bool res = xcbRandrHandleCrtc (data , outputInfoReply -> crtc , name , primary , outputInfoReply , displayType , edidData , edidLength );
250
-
251
- return res ;
252
- }
253
-
254
- static bool xcbRandrHandleMonitor (XcbRandrData * data , xcb_randr_monitor_info_t * monitor )
245
+ static bool xcbRandrHandleMonitor (XcbRandrData * data , xcb_randr_monitor_info_t * monitor , struct xcb_randr_get_screen_resources_current_reply_t * screenResources , uint8_t bitDepth , double scaleFactor )
255
246
{
256
247
//for some reasons, we have to construct this our self
257
248
xcb_randr_output_iterator_t outputIterator = {
@@ -275,18 +266,20 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t*
275
266
276
267
while (outputIterator .rem > 0 )
277
268
{
278
- if (xcbRandrHandleOutput (data , * outputIterator .data , & name , monitor -> primary , displayType ))
269
+ if (xcbRandrHandleOutput (data , * outputIterator .data , & name , monitor -> primary , displayType , screenResources , bitDepth , scaleFactor ))
279
270
foundOutput = true;
280
271
data -> ffxcb_randr_output_next (& outputIterator );
281
- };
272
+ }
282
273
283
- return foundOutput ? true : !!ffdsAppendDisplay (
274
+ if (foundOutput ) return true;
275
+
276
+ FFDisplayResult * display = ffdsAppendDisplay (
284
277
data -> result ,
285
278
(uint32_t ) monitor -> width ,
286
279
(uint32_t ) monitor -> height ,
287
280
0 ,
288
- (uint32_t ) monitor -> width ,
289
- (uint32_t ) monitor -> height ,
281
+ (uint32_t ) ( monitor -> width / scaleFactor + .5 ) ,
282
+ (uint32_t ) ( monitor -> height / scaleFactor + .5 ) ,
290
283
0 , 0 , 0 ,
291
284
0 ,
292
285
& name ,
@@ -297,6 +290,8 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t*
297
290
(uint32_t ) monitor -> height_in_millimeters ,
298
291
"xcb-randr-monitor"
299
292
);
293
+ if (display ) display -> bitDepth = bitDepth ;
294
+ return !!display ;
300
295
}
301
296
302
297
static bool xcbRandrHandleMonitors (XcbRandrData * data , xcb_screen_t * screen )
@@ -306,13 +301,27 @@ static bool xcbRandrHandleMonitors(XcbRandrData* data, xcb_screen_t* screen)
306
301
if (monitorsReply == NULL )
307
302
return false;
308
303
304
+ //Init screen resources. They are used to iterate over all modes. xcbRandrHandleMode checks for " == NULL", to fail as late as possible.
305
+ xcb_randr_get_screen_resources_current_cookie_t screenResourcesCookie = data -> ffxcb_randr_get_screen_resources_current (data -> connection , screen -> root );
306
+ FF_AUTO_FREE struct xcb_randr_get_screen_resources_current_reply_t * screenResources = data -> ffxcb_randr_get_screen_resources_current_reply (data -> connection , screenResourcesCookie , NULL );
307
+
308
+ double scaleFactor = 1 ;
309
+ FF_AUTO_FREE const char * resourceManager = xcbGetProperty (& data -> propData , data -> connection , screen -> root , "RESOURCE_MANAGER" );
310
+ if (resourceManager )
311
+ {
312
+ FF_STRBUF_AUTO_DESTROY dpi = ffStrbufCreate ();
313
+ if (ffParsePropLines (resourceManager , "Xft.dpi:" , & dpi ))
314
+ scaleFactor = ffStrbufToDouble (& dpi , 96 ) / 96 ;
315
+ }
316
+ uint8_t bitDepth = (uint8_t ) (screen -> root_depth / 3 );
317
+
309
318
xcb_randr_monitor_info_iterator_t monitorInfoIterator = data -> ffxcb_randr_get_monitors_monitors_iterator (monitorsReply );
310
319
311
320
bool foundMonitor = false;
312
321
313
322
while (monitorInfoIterator .rem > 0 )
314
323
{
315
- if (xcbRandrHandleMonitor (data , monitorInfoIterator .data ))
324
+ if (xcbRandrHandleMonitor (data , monitorInfoIterator .data , screenResources , bitDepth , scaleFactor ))
316
325
foundMonitor = true;
317
326
data -> ffxcb_randr_monitor_info_next (& monitorInfoIterator );
318
327
}
@@ -322,17 +331,8 @@ static bool xcbRandrHandleMonitors(XcbRandrData* data, xcb_screen_t* screen)
322
331
323
332
static void xcbRandrHandleScreen (XcbRandrData * data , xcb_screen_t * screen )
324
333
{
325
- //Init screen resources. They are used to iterate over all modes. xcbRandrHandleMode checks for " == NULL", to fail as late as possible.
326
- xcb_randr_get_screen_resources_current_cookie_t screenResourcesCookie = data -> ffxcb_randr_get_screen_resources_current (data -> connection , screen -> root );
327
-
328
- data -> screenResources = data -> ffxcb_randr_get_screen_resources_current_reply (data -> connection , screenResourcesCookie , NULL );
329
-
330
334
//With all the initialisation done, start the detection
331
- bool ret = xcbRandrHandleMonitors (data , screen );
332
-
333
- free (data -> screenResources );
334
-
335
- if (ret )
335
+ if (xcbRandrHandleMonitors (data , screen ))
336
336
return ;
337
337
338
338
//If detetction failed, fallback to screen = monitor, like in the libxcb.so implementation
@@ -348,7 +348,7 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen)
348
348
NULL ,
349
349
FF_DISPLAY_TYPE_UNKNOWN ,
350
350
false,
351
- 0 ,
351
+ ( uint64_t ) screen -> root ,
352
352
(uint32_t ) screen -> width_in_millimeters ,
353
353
(uint32_t ) screen -> height_in_millimeters ,
354
354
"xcb-randr-screen"
0 commit comments