ScrapExplorer - x11_monitor.c

Home / ext / glfw / src Lines: 1 | Size: 20319 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1//======================================================================== 2// GLFW 3.5 X11 - www.glfw.org 3//------------------------------------------------------------------------ 4// Copyright (c) 2002-2006 Marcus Geelnard 5// Copyright (c) 2006-2019 Camilla Löwy <[email protected]> 6// 7// This software is provided 'as-is', without any express or implied 8// warranty. In no event will the authors be held liable for any damages 9// arising from the use of this software. 10// 11// Permission is granted to anyone to use this software for any purpose, 12// including commercial applications, and to alter it and redistribute it 13// freely, subject to the following restrictions: 14// 15// 1. The origin of this software must not be misrepresented; you must not 16// claim that you wrote the original software. If you use this software 17// in a product, an acknowledgment in the product documentation would 18// be appreciated but is not required. 19// 20// 2. Altered source versions must be plainly marked as such, and must not 21// be misrepresented as being the original software. 22// 23// 3. This notice may not be removed or altered from any source 24// distribution. 25// 26//======================================================================== 27 28#include "internal.h" 29 30#if defined(_GLFW_X11) 31 32#include <limits.h> 33#include <stdlib.h> 34#include <string.h> 35#include <math.h> 36#include <assert.h> 37 38 39// Check whether the display mode should be included in enumeration 40// 41static GLFWbool modeIsGood(const XRRModeInfo* mi) 42{ 43 return (mi->modeFlags & RR_Interlace) == 0; 44} 45 46// Calculates the refresh rate, in Hz, from the specified RandR mode info 47// 48static int calculateRefreshRate(const XRRModeInfo* mi) 49{ 50 if (mi->hTotal && mi->vTotal) 51 return (int) round((double) mi->dotClock / ((double) mi->hTotal * (double) mi->vTotal)); 52 else 53 return 0; 54} 55 56// Returns the mode info for a RandR mode XID 57// 58static const XRRModeInfo* getModeInfo(const XRRScreenResources* sr, RRMode id) 59{ 60 for (int i = 0; i < sr->nmode; i++) 61 { 62 if (sr->modes[i].id == id) 63 return sr->modes + i; 64 } 65 66 return NULL; 67} 68 69// Convert RandR mode info to GLFW video mode 70// 71static GLFWvidmode vidmodeFromModeInfo(const XRRModeInfo* mi, 72 const XRRCrtcInfo* ci) 73{ 74 GLFWvidmode mode; 75 76 if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270) 77 { 78 mode.width = mi->height; 79 mode.height = mi->width; 80 } 81 else 82 { 83 mode.width = mi->width; 84 mode.height = mi->height; 85 } 86 87 mode.refreshRate = calculateRefreshRate(mi); 88 89 _glfwSplitBPP(DefaultDepth(_glfw.x11.display, _glfw.x11.screen), 90 &mode.redBits, &mode.greenBits, &mode.blueBits); 91 92 return mode; 93} 94 95 96////////////////////////////////////////////////////////////////////////// 97////// GLFW internal API ////// 98////////////////////////////////////////////////////////////////////////// 99 100// Poll for changes in the set of connected monitors 101// 102void _glfwPollMonitorsX11(void) 103{ 104 if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) 105 { 106 int disconnectedCount, screenCount = 0; 107 _GLFWmonitor** disconnected = NULL; 108 XineramaScreenInfo* screens = NULL; 109 XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, 110 _glfw.x11.root); 111 RROutput primary = XRRGetOutputPrimary(_glfw.x11.display, 112 _glfw.x11.root); 113 114 if (_glfw.x11.xinerama.available) 115 screens = XineramaQueryScreens(_glfw.x11.display, &screenCount); 116 117 disconnectedCount = _glfw.monitorCount; 118 if (disconnectedCount) 119 { 120 disconnected = _glfw_calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*)); 121 memcpy(disconnected, 122 _glfw.monitors, 123 _glfw.monitorCount * sizeof(_GLFWmonitor*)); 124 } 125 126 for (int i = 0; i < sr->noutput; i++) 127 { 128 int j, type, widthMM, heightMM; 129 130 XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, sr->outputs[i]); 131 if (oi->connection != RR_Connected || oi->crtc == None) 132 { 133 XRRFreeOutputInfo(oi); 134 continue; 135 } 136 137 for (j = 0; j < disconnectedCount; j++) 138 { 139 if (disconnected[j] && 140 disconnected[j]->x11.output == sr->outputs[i]) 141 { 142 disconnected[j] = NULL; 143 break; 144 } 145 } 146 147 if (j < disconnectedCount) 148 { 149 XRRFreeOutputInfo(oi); 150 continue; 151 } 152 153 XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc); 154 if (!ci) { 155 XRRFreeOutputInfo(oi); 156 continue; 157 } 158 159 if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270) 160 { 161 widthMM = oi->mm_height; 162 heightMM = oi->mm_width; 163 } 164 else 165 { 166 widthMM = oi->mm_width; 167 heightMM = oi->mm_height; 168 } 169 170 if (widthMM <= 0 || heightMM <= 0) 171 { 172 // HACK: If RandR does not provide a physical size, assume the 173 // X11 default 96 DPI and calculate from the CRTC viewport 174 // NOTE: These members are affected by rotation, unlike the mode 175 // info and output info members 176 widthMM = (int) (ci->width * 25.4f / 96.f); 177 heightMM = (int) (ci->height * 25.4f / 96.f); 178 } 179 180 _GLFWmonitor* monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM); 181 monitor->x11.output = sr->outputs[i]; 182 monitor->x11.crtc = oi->crtc; 183 184 for (j = 0; j < screenCount; j++) 185 { 186 if (screens[j].x_org == ci->x && 187 screens[j].y_org == ci->y && 188 screens[j].width == ci->width && 189 screens[j].height == ci->height) 190 { 191 monitor->x11.index = j; 192 break; 193 } 194 } 195 196 if (monitor->x11.output == primary) 197 type = _GLFW_INSERT_FIRST; 198 else 199 type = _GLFW_INSERT_LAST; 200 201 _glfwInputMonitor(monitor, GLFW_CONNECTED, type); 202 203 XRRFreeOutputInfo(oi); 204 XRRFreeCrtcInfo(ci); 205 } 206 207 XRRFreeScreenResources(sr); 208 209 if (screens) 210 XFree(screens); 211 212 for (int i = 0; i < disconnectedCount; i++) 213 { 214 if (disconnected[i]) 215 _glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0); 216 } 217 218 _glfw_free(disconnected); 219 } 220 else 221 { 222 const int widthMM = DisplayWidthMM(_glfw.x11.display, _glfw.x11.screen); 223 const int heightMM = DisplayHeightMM(_glfw.x11.display, _glfw.x11.screen); 224 225 _glfwInputMonitor(_glfwAllocMonitor("Display", widthMM, heightMM), 226 GLFW_CONNECTED, 227 _GLFW_INSERT_FIRST); 228 } 229} 230 231// Set the current video mode for the specified monitor 232// 233void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired) 234{ 235 if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) 236 { 237 GLFWvidmode current; 238 RRMode native = None; 239 240 const GLFWvidmode* best = _glfwChooseVideoMode(monitor, desired); 241 _glfwGetVideoModeX11(monitor, &current); 242 if (_glfwCompareVideoModes(&current, best) == 0) 243 return; 244 245 XRRScreenResources* sr = 246 XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); 247 XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); 248 XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output); 249 250 for (int i = 0; i < oi->nmode; i++) 251 { 252 const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]); 253 if (!modeIsGood(mi)) 254 continue; 255 256 const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci); 257 if (_glfwCompareVideoModes(best, &mode) == 0) 258 { 259 native = mi->id; 260 break; 261 } 262 } 263 264 if (native) 265 { 266 if (monitor->x11.oldMode == None) 267 monitor->x11.oldMode = ci->mode; 268 269 XRRSetCrtcConfig(_glfw.x11.display, 270 sr, monitor->x11.crtc, 271 CurrentTime, 272 ci->x, ci->y, 273 native, 274 ci->rotation, 275 ci->outputs, 276 ci->noutput); 277 } 278 279 XRRFreeOutputInfo(oi); 280 XRRFreeCrtcInfo(ci); 281 XRRFreeScreenResources(sr); 282 } 283} 284 285// Restore the saved (original) video mode for the specified monitor 286// 287void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor) 288{ 289 if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) 290 { 291 if (monitor->x11.oldMode == None) 292 return; 293 294 XRRScreenResources* sr = 295 XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); 296 XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); 297 298 XRRSetCrtcConfig(_glfw.x11.display, 299 sr, monitor->x11.crtc, 300 CurrentTime, 301 ci->x, ci->y, 302 monitor->x11.oldMode, 303 ci->rotation, 304 ci->outputs, 305 ci->noutput); 306 307 XRRFreeCrtcInfo(ci); 308 XRRFreeScreenResources(sr); 309 310 monitor->x11.oldMode = None; 311 } 312} 313 314 315////////////////////////////////////////////////////////////////////////// 316////// GLFW platform API ////// 317////////////////////////////////////////////////////////////////////////// 318 319void _glfwFreeMonitorX11(_GLFWmonitor* monitor) 320{ 321} 322 323void _glfwGetMonitorPosX11(_GLFWmonitor* monitor, int* xpos, int* ypos) 324{ 325 if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) 326 { 327 XRRScreenResources* sr = 328 XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); 329 XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); 330 331 if (ci) 332 { 333 if (xpos) 334 *xpos = ci->x; 335 if (ypos) 336 *ypos = ci->y; 337 338 XRRFreeCrtcInfo(ci); 339 } 340 341 XRRFreeScreenResources(sr); 342 } 343} 344 345void _glfwGetMonitorContentScaleX11(_GLFWmonitor* monitor, 346 float* xscale, float* yscale) 347{ 348 if (xscale) 349 *xscale = _glfw.x11.contentScaleX; 350 if (yscale) 351 *yscale = _glfw.x11.contentScaleY; 352} 353 354void _glfwGetMonitorWorkareaX11(_GLFWmonitor* monitor, 355 int* xpos, int* ypos, 356 int* width, int* height) 357{ 358 int areaX = 0, areaY = 0, areaWidth = 0, areaHeight = 0; 359 360 if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) 361 { 362 XRRScreenResources* sr = 363 XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); 364 XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); 365 366 areaX = ci->x; 367 areaY = ci->y; 368 369 const XRRModeInfo* mi = getModeInfo(sr, ci->mode); 370 371 if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270) 372 { 373 areaWidth = mi->height; 374 areaHeight = mi->width; 375 } 376 else 377 { 378 areaWidth = mi->width; 379 areaHeight = mi->height; 380 } 381 382 XRRFreeCrtcInfo(ci); 383 XRRFreeScreenResources(sr); 384 } 385 else 386 { 387 areaWidth = DisplayWidth(_glfw.x11.display, _glfw.x11.screen); 388 areaHeight = DisplayHeight(_glfw.x11.display, _glfw.x11.screen); 389 } 390 391 if (_glfw.x11.NET_WORKAREA && _glfw.x11.NET_CURRENT_DESKTOP) 392 { 393 Atom* extents = NULL; 394 Atom* desktop = NULL; 395 const unsigned long extentCount = 396 _glfwGetWindowPropertyX11(_glfw.x11.root, 397 _glfw.x11.NET_WORKAREA, 398 XA_CARDINAL, 399 (unsigned char**) &extents); 400 401 if (_glfwGetWindowPropertyX11(_glfw.x11.root, 402 _glfw.x11.NET_CURRENT_DESKTOP, 403 XA_CARDINAL, 404 (unsigned char**) &desktop) > 0) 405 { 406 if (extentCount >= 4 && *desktop < extentCount / 4) 407 { 408 const int globalX = extents[*desktop * 4 + 0]; 409 const int globalY = extents[*desktop * 4 + 1]; 410 const int globalWidth = extents[*desktop * 4 + 2]; 411 const int globalHeight = extents[*desktop * 4 + 3]; 412 413 if (areaX < globalX) 414 { 415 areaWidth -= globalX - areaX; 416 areaX = globalX; 417 } 418 419 if (areaY < globalY) 420 { 421 areaHeight -= globalY - areaY; 422 areaY = globalY; 423 } 424 425 if (areaX + areaWidth > globalX + globalWidth) 426 areaWidth = globalX - areaX + globalWidth; 427 if (areaY + areaHeight > globalY + globalHeight) 428 areaHeight = globalY - areaY + globalHeight; 429 } 430 } 431 432 if (extents) 433 XFree(extents); 434 if (desktop) 435 XFree(desktop); 436 } 437 438 if (xpos) 439 *xpos = areaX; 440 if (ypos) 441 *ypos = areaY; 442 if (width) 443 *width = areaWidth; 444 if (height) 445 *height = areaHeight; 446} 447 448GLFWvidmode* _glfwGetVideoModesX11(_GLFWmonitor* monitor, int* count) 449{ 450 GLFWvidmode* result; 451 452 *count = 0; 453 454 if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) 455 { 456 XRRScreenResources* sr = 457 XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); 458 XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); 459 XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output); 460 461 result = _glfw_calloc(oi->nmode, sizeof(GLFWvidmode)); 462 463 for (int i = 0; i < oi->nmode; i++) 464 { 465 const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]); 466 if (!modeIsGood(mi)) 467 continue; 468 469 const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci); 470 int j; 471 472 for (j = 0; j < *count; j++) 473 { 474 if (_glfwCompareVideoModes(result + j, &mode) == 0) 475 break; 476 } 477 478 // Skip duplicate modes 479 if (j < *count) 480 continue; 481 482 (*count)++; 483 result[*count - 1] = mode; 484 } 485 486 XRRFreeOutputInfo(oi); 487 XRRFreeCrtcInfo(ci); 488 XRRFreeScreenResources(sr); 489 } 490 else 491 { 492 *count = 1; 493 result = _glfw_calloc(1, sizeof(GLFWvidmode)); 494 _glfwGetVideoModeX11(monitor, result); 495 } 496 497 return result; 498} 499 500GLFWbool _glfwGetVideoModeX11(_GLFWmonitor* monitor, GLFWvidmode* mode) 501{ 502 if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) 503 { 504 XRRScreenResources* sr = 505 XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); 506 const XRRModeInfo* mi = NULL; 507 508 XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); 509 if (ci) 510 { 511 mi = getModeInfo(sr, ci->mode); 512 if (mi) 513 *mode = vidmodeFromModeInfo(mi, ci); 514 515 XRRFreeCrtcInfo(ci); 516 } 517 518 XRRFreeScreenResources(sr); 519 520 if (!mi) 521 { 522 _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to query video mode"); 523 return GLFW_FALSE; 524 } 525 } 526 else 527 { 528 mode->width = DisplayWidth(_glfw.x11.display, _glfw.x11.screen); 529 mode->height = DisplayHeight(_glfw.x11.display, _glfw.x11.screen); 530 mode->refreshRate = 0; 531 532 _glfwSplitBPP(DefaultDepth(_glfw.x11.display, _glfw.x11.screen), 533 &mode->redBits, &mode->greenBits, &mode->blueBits); 534 } 535 536 return GLFW_TRUE; 537} 538 539GLFWbool _glfwGetGammaRampX11(_GLFWmonitor* monitor, GLFWgammaramp* ramp) 540{ 541 if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken) 542 { 543 const size_t size = XRRGetCrtcGammaSize(_glfw.x11.display, 544 monitor->x11.crtc); 545 XRRCrtcGamma* gamma = XRRGetCrtcGamma(_glfw.x11.display, 546 monitor->x11.crtc); 547 548 _glfwAllocGammaArrays(ramp, size); 549 550 memcpy(ramp->red, gamma->red, size * sizeof(unsigned short)); 551 memcpy(ramp->green, gamma->green, size * sizeof(unsigned short)); 552 memcpy(ramp->blue, gamma->blue, size * sizeof(unsigned short)); 553 554 XRRFreeGamma(gamma); 555 return GLFW_TRUE; 556 } 557 else if (_glfw.x11.vidmode.available) 558 { 559 int size; 560 XF86VidModeGetGammaRampSize(_glfw.x11.display, _glfw.x11.screen, &size); 561 562 _glfwAllocGammaArrays(ramp, size); 563 564 XF86VidModeGetGammaRamp(_glfw.x11.display, 565 _glfw.x11.screen, 566 ramp->size, ramp->red, ramp->green, ramp->blue); 567 return GLFW_TRUE; 568 } 569 else 570 { 571 _glfwInputError(GLFW_PLATFORM_ERROR, 572 "X11: Gamma ramp access not supported by server"); 573 return GLFW_FALSE; 574 } 575} 576 577void _glfwSetGammaRampX11(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) 578{ 579 if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken) 580 { 581 if (XRRGetCrtcGammaSize(_glfw.x11.display, monitor->x11.crtc) != ramp->size) 582 { 583 _glfwInputError(GLFW_PLATFORM_ERROR, 584 "X11: Gamma ramp size must match current ramp size"); 585 return; 586 } 587 588 XRRCrtcGamma* gamma = XRRAllocGamma(ramp->size); 589 590 memcpy(gamma->red, ramp->red, ramp->size * sizeof(unsigned short)); 591 memcpy(gamma->green, ramp->green, ramp->size * sizeof(unsigned short)); 592 memcpy(gamma->blue, ramp->blue, ramp->size * sizeof(unsigned short)); 593 594 XRRSetCrtcGamma(_glfw.x11.display, monitor->x11.crtc, gamma); 595 XRRFreeGamma(gamma); 596 } 597 else if (_glfw.x11.vidmode.available) 598 { 599 XF86VidModeSetGammaRamp(_glfw.x11.display, 600 _glfw.x11.screen, 601 ramp->size, 602 (unsigned short*) ramp->red, 603 (unsigned short*) ramp->green, 604 (unsigned short*) ramp->blue); 605 } 606 else 607 { 608 _glfwInputError(GLFW_PLATFORM_ERROR, 609 "X11: Gamma ramp access not supported by server"); 610 } 611} 612 613 614////////////////////////////////////////////////////////////////////////// 615////// GLFW native API ////// 616////////////////////////////////////////////////////////////////////////// 617 618GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* handle) 619{ 620 _GLFW_REQUIRE_INIT_OR_RETURN(None); 621 622 if (_glfw.platform.platformID != GLFW_PLATFORM_X11) 623 { 624 _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "X11: Platform not initialized"); 625 return None; 626 } 627 628 _GLFWmonitor* monitor = (_GLFWmonitor*) handle; 629 assert(monitor != NULL); 630 631 return monitor->x11.crtc; 632} 633 634GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* handle) 635{ 636 _GLFW_REQUIRE_INIT_OR_RETURN(None); 637 638 if (_glfw.platform.platformID != GLFW_PLATFORM_X11) 639 { 640 _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "X11: Platform not initialized"); 641 return None; 642 } 643 644 _GLFWmonitor* monitor = (_GLFWmonitor*) handle; 645 assert(monitor != NULL); 646 647 return monitor->x11.output; 648} 649 650#endif // _GLFW_X11 651 652
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.