You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. var udev = require("../../udev");
  2. var xrandr = require("./xrandr");
  3. var table = require("../../js/table");
  4. var spawn = require("child_process").spawn;
  5. exports.start = start;
  6. exports.stop = stop;
  7. exports.event = event;
  8. exports.list = list;
  9. var conf;
  10. var logger;
  11. var modules;
  12. function findMode(display, mode) {
  13. if (mode === "max")
  14. return display.modes[0];
  15. for (var i in display.modes) {
  16. if (display.modes[i].resStr == mode)
  17. return display.modes[i];
  18. }
  19. return null;
  20. }
  21. function findRate(mode, rate) {
  22. if (rate === "max")
  23. return mode.rates[0];
  24. for (var i in mode.rates) {
  25. if (mode.rates[i] == rate)
  26. return mode.rates[i];
  27. }
  28. return null;
  29. }
  30. function applyRule(primary, rule, display) {
  31. var cmd = "xrandr";
  32. var args = [ "--output", display.id ];
  33. if (rule.rate != null && rule.mode == null)
  34. return logger.warn("Display "+rule.name+": 'rate' specified without 'mode'");
  35. var mode;
  36. if (rule.mode != null) {
  37. mode = findMode(display, rule.mode);
  38. if (mode == null)
  39. return logger.warn(
  40. "Display "+rule.name+": Invalid mode: "+rule.res);
  41. args.push("--mode");
  42. args.push(mode.resStr);
  43. }
  44. var rate;
  45. if (rule.rate != null) {
  46. rate = findRate(mode, rule.rate);
  47. if (rate == null)
  48. return logger.warn(
  49. "Display "+rule.name+": Invalid rate: "+rule.rate);
  50. args.push("--rate");
  51. args.push(rate);
  52. }
  53. if (rule.where) {
  54. var w = rule.where;
  55. for (var i in w) {
  56. if (
  57. i !== "left-of" && i !== "right-of" &&
  58. i !== "above" && i !== "below") {
  59. return logger.warn(
  60. "Display "+rule.name+": Invalid 'where' value: "+i);
  61. }
  62. if (w[i] === "primary" && display === primary)
  63. continue;
  64. var id;
  65. if (w[i] === "primary") {
  66. id = primary.id;
  67. } else {
  68. id = w[i];
  69. }
  70. args.push("--"+i);
  71. args.push(id);
  72. }
  73. }
  74. var child = spawn(cmd, args);
  75. child.stderr.on("data", d => logger.warn("xrandr:", d.toString()));
  76. }
  77. function onchange() {
  78. if (conf == null) {
  79. setTimeout(() => modules.wallpaper.event("reload"), 0);
  80. logger.info("No displays configured.");
  81. return;
  82. }
  83. xrandr.list(data => {
  84. var displays = data.displays.filter(d => d.connected);
  85. var primary = displays.filter(d => d.primary)[0];
  86. conf.forEach(entry => {
  87. displays.forEach(disp => {
  88. if (entry.name !== "*" && entry.name !== disp.id)
  89. return;
  90. applyRule(primary, entry, disp);
  91. });
  92. });
  93. setTimeout(() => modules.wallpaper.event("reload"), 400);
  94. });
  95. }
  96. function start(conf_, logger_, modules_) {
  97. conf = conf_ || conf;
  98. logger = logger_ || logger;
  99. modules = modules_ || modules;
  100. onchange();
  101. udev.monitor("drm", onchange);
  102. }
  103. function stop(cb) {
  104. udev.unmonitor("drm", onchange);
  105. cb();
  106. }
  107. function event(name, ...params) {
  108. switch (name) {
  109. default:
  110. logger.warn("Unknown event:", name);
  111. }
  112. }
  113. function list(cb) {
  114. xrandr.list(devs => {
  115. devs.displays.forEach(dev => {
  116. console.error(
  117. "\tname: "+dev.id+
  118. (dev.connected ? ", connected" : "")+
  119. (dev.primary ? ", primary" : ""));
  120. var data = [];
  121. for (var i in dev.modes) {
  122. var mode = dev.modes[i];
  123. data[i] = [];
  124. var d = data[i];
  125. d.push("mode: "+mode.resStr+",");
  126. d.push("rate:");
  127. mode.rates.forEach(r => d.push(r));
  128. }
  129. table(console.error.bind(console), data, "\t\t");
  130. });
  131. cb();
  132. });
  133. }