summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2018-08-31 10:57:39 +0200
committerSimon Rettberg2018-08-31 10:57:39 +0200
commit64af75c336424b6dfe0a114a4697fb522a6169e5 (patch)
tree3d6794b2ad0b55e33df109035f41a8291eddf864
parentMake wakeup work (diff)
downloadbeamergui-64af75c336424b6dfe0a114a4697fb522a6169e5.tar.gz
beamergui-64af75c336424b6dfe0a114a4697fb522a6169e5.tar.xz
beamergui-64af75c336424b6dfe0a114a4697fb522a6169e5.zip
Update
-rw-r--r--LICENSE2
-rw-r--r--src/i18n/de.ts26
-rw-r--r--src/icons.qrc5
-rw-r--r--src/icons/projector_icon.svg114
-rw-r--r--src/icons/refresh_icon.svg37
-rw-r--r--src/icons/screen_icon.svg39
-rw-r--r--src/main.cpp29
-rw-r--r--src/widget.cpp182
-rw-r--r--src/widget.h3
-rw-r--r--src/widget.ui23
-rw-r--r--src/xprivate.cpp38
-rw-r--r--src/xx.cpp77
-rw-r--r--src/xx.h16
-rw-r--r--udev/99-beamergui.rules3
14 files changed, 386 insertions, 208 deletions
diff --git a/LICENSE b/LICENSE
index c56fa74..bd83a08 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,7 +1,7 @@
GPL blabla
Icons:
-Projector:
+Projector + Refresh:
Icons made by "http://www.freepik.com" Freepik, from "https://www.flaticon.com/", "Creative Commons BY 3.0" (CC 3.0 BY)
Screen:
diff --git a/src/i18n/de.ts b/src/i18n/de.ts
index b8537b6..5589628 100644
--- a/src/i18n/de.ts
+++ b/src/i18n/de.ts
@@ -4,7 +4,7 @@
<context>
<name>QCoreApplication</name>
<message>
- <location filename="../widget.cpp" line="191"/>
+ <location filename="../widget.cpp" line="216"/>
<source>%1x%2</source>
<translation type="unfinished"></translation>
</message>
@@ -67,37 +67,37 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../widget.cpp" line="327"/>
+ <location filename="../widget.cpp" line="364"/>
<source>(off)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../widget.cpp" line="359"/>
+ <location filename="../widget.cpp" line="396"/>
<source>Output</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../widget.cpp" line="360"/>
+ <location filename="../widget.cpp" line="397"/>
<source>Position</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../widget.cpp" line="471"/>
+ <location filename="../widget.cpp" line="508"/>
<source>Do you want to keep this resolution?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../widget.cpp" line="472"/>
+ <location filename="../widget.cpp" line="509"/>
<source>Keep</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../widget.cpp" line="568"/>
+ <location filename="../widget.cpp" line="605"/>
<source>Confirm</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../widget.cpp" line="569"/>
+ <location filename="../widget.cpp" line="606"/>
<source>This terminates the GUI.
It will not pop up again if further screens are connected.
Are you sure?</source>
@@ -107,27 +107,27 @@ Are you sure?</source>
<context>
<name>main</name>
<message>
- <location filename="../main.cpp" line="75"/>
+ <location filename="../main.cpp" line="86"/>
<source>Automatically configure modes and set up screens.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../main.cpp" line="79"/>
+ <location filename="../main.cpp" line="90"/>
<source>Show config GUI if more than one screen is connected.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../main.cpp" line="83"/>
+ <location filename="../main.cpp" line="94"/>
<source>Keep running in background and show GUI again when number of screens changes.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../main.cpp" line="87"/>
+ <location filename="../main.cpp" line="98"/>
<source>Test mode, don&apos;t actually apply any changes.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../main.cpp" line="91"/>
+ <location filename="../main.cpp" line="102"/>
<source>Connect to system bus to trigger wakeup of wainting beamergui.</source>
<translation type="unfinished"></translation>
</message>
diff --git a/src/icons.qrc b/src/icons.qrc
index 3a700e5..164f3b1 100644
--- a/src/icons.qrc
+++ b/src/icons.qrc
@@ -1,7 +1,8 @@
<RCC>
- <qresource>
+ <qresource prefix="/">
<file alias="projector">icons/projector_icon.svg</file>
<file alias="screen">icons/screen_icon.svg</file>
<file alias="check">icons/checkmark.svg</file>
- </qresource>
+ <file alias="refresh">icons/refresh_icon.svg</file>
+ </qresource>
</RCC>
diff --git a/src/icons/projector_icon.svg b/src/icons/projector_icon.svg
index a22f105..d145e98 100644
--- a/src/icons/projector_icon.svg
+++ b/src/icons/projector_icon.svg
@@ -1,65 +1,53 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- viewBox="0 0 494.516 494.516" style="enable-background:new 0 0 494.516 494.516;" xml:space="preserve">
-<g>
- <path d="M264.787,220.756c1.088,0,2.176-0.415,3.004-1.245l23.453-23.454c1.66-1.66,1.66-4.351,0-6.011
- c-1.658-1.659-4.352-1.659-6.01,0l-23.453,23.454c-1.66,1.66-1.66,4.351,0,6.011C262.611,220.341,263.699,220.756,264.787,220.756z
- "/>
- <path d="M316.324,190.047l-54.543,54.544c-1.66,1.66-1.66,4.351,0,6.011c0.83,0.83,1.918,1.245,3.006,1.245
- c1.088,0,2.176-0.415,3.004-1.245l54.543-54.544c1.66-1.66,1.66-4.351,0-6.011C320.674,188.388,317.982,188.388,316.324,190.047z"
- />
- <path d="M308.49,167.516c-39.314,0-71.301,31.985-71.301,71.299c0,39.315,31.986,71.3,71.301,71.3
- c39.314,0,71.299-31.985,71.299-71.3C379.789,199.501,347.805,167.516,308.49,167.516z M308.49,301.615
- c-34.629,0-62.801-28.172-62.801-62.8c0-34.627,28.172-62.799,62.801-62.799c34.627,0,62.799,28.172,62.799,62.799
- C371.289,273.443,343.117,301.615,308.49,301.615z"/>
- <path d="M421.185,151.672H352.9c-13.334-6.823-28.43-10.676-44.41-10.676c-15.979,0-31.076,3.853-44.41,10.676H73.33
- C32.896,151.672,0,184.568,0,225.003v27.626c0,37.031,27.598,67.72,63.303,72.626v7.565c0,11.413,9.285,20.699,20.699,20.699
- h16.447c11.414,0,20.699-9.286,20.699-20.699v-6.861H264.08c13.334,6.823,28.432,10.676,44.41,10.676h0.002
- c15.979,0,31.074-3.853,44.41-10.676h20.465v6.861c0,11.413,9.285,20.699,20.699,20.699h16.447
- c11.414,0,20.699-9.286,20.699-20.699v-7.565c35.705-4.906,63.303-35.595,63.303-72.626v-27.626
- C494.516,184.568,461.621,151.672,421.185,151.672z M112.648,332.82c0,6.727-5.473,12.199-12.199,12.199H84.002
- c-6.727,0-12.199-5.472-12.199-12.199v-6.9c0.51,0.01,1.016,0.039,1.527,0.039h39.318V332.82z M73.33,317.459
- c-21.209,0-40.072-10.238-51.908-26.032h51.223c2.348,0,4.25-1.903,4.25-4.25c0-2.347-1.902-4.25-4.25-4.25H16.039
- c-4.805-9.049-7.539-19.358-7.539-30.298v-9.564h188.621c2.348,0,4.25-1.903,4.25-4.25s-1.902-4.25-4.25-4.25H8.5v-9.562
- c0-6.332,0.928-12.448,2.629-18.237h101.617c2.348,0,4.25-1.903,4.25-4.25s-1.902-4.25-4.25-4.25H14.293
- c10.205-22.442,32.82-38.094,59.037-38.094h177.057c-24.076,17.836-39.717,46.446-39.717,78.643
- c0,32.197,15.641,60.808,39.717,78.644H73.33z M308.49,328.135c-49.25,0-89.32-40.068-89.32-89.319
- c0-49.251,40.07-89.319,89.32-89.319c49.252,0,89.32,40.068,89.32,89.319c0,49.251-40.068,89.319-89.318,89.319H308.49z
- M422.713,332.82c0,6.727-5.473,12.199-12.199,12.199h-16.447c-6.727,0-12.199-5.472-12.199-12.199v-6.861h39.318
- c0.512,0,1.018-0.028,1.527-0.039V332.82z M421.185,317.459h-54.592c24.078-17.836,39.717-46.446,39.717-78.644
- c0-32.197-15.641-60.807-39.719-78.643h54.594c35.748,0,64.83,29.083,64.83,64.831v11.137h-21.688c-2.348,0-4.25,1.903-4.25,4.25
- s1.902,4.25,4.25,4.25h21.688v7.989C486.016,288.376,456.934,317.459,421.185,317.459z"/>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
+<?xml version="1.0" encoding="utf-8"?>
+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" width="506" height="226">
+<g transform="translate(5.6843745,0)">
+ <path d="m 264.787,86.533051 c 1.088,0 2.176,-0.415 3.004,-1.245 l 23.453,-23.454 c 1.66,-1.66 1.66,-4.351
+ 0,-6.011 -1.658,-1.659 -4.352,-1.659 -6.01,0 l -23.453,23.454 c -1.66,1.66 -1.66,4.351 0,6.011 0.83,0.83
+ 1.918,1.245 3.006,1.245 z"/>
+ <path d="m 316.324,55.824051 -54.543,54.543999 c -1.66,1.66 -1.66,4.351 0,6.011 0.83,0.83 1.918,1.245
+ 3.006,1.245 1.088,0 2.176,-0.415 3.004,-1.245 l 54.543,-54.543999 c 1.66,-1.66 1.66,-4.351 0,-6.011
+ -1.66,-1.659 -4.352,-1.659 -6.01,0 z"/>
+ <path d="m 306.62695,31.316111 c -33.18717,0.25249 -63.80337,25.96705 -69.95117,58.54883 -6.90988,31.106029
+ 9.40608,65.280469 37.80613,79.642789 28.28598,15.46633 66.25331,8.906 87.74203,-15.11728
+ 22.53369,-23.43249 26.00409,-62.240189 7.987,-89.298949 -13.48926,-21.33267 -38.32032,-34.63681
+ -63.58399,-33.77539 z m 1.86328,12.47656 c 29.01072,-0.63446 56.23968,22.6771 60.10157,51.57618
+ 5.00138,28.643539 -13.80349,58.797369 -41.59946,67.141169 -26.27167,8.9673 -57.71075,-3.16886
+ -71.22672,-27.66266 -14.84977,-24.69204 -8.54358,-59.307669 14.08985,-77.166009 10.82519,-8.97579
+ 24.65521,-13.93047 38.63476,-13.88868 z"/>
+ <path d="m 306.95898,2.7848606 c -15.16014,0.20678 -30.26935,3.86572 -43.82421,10.6640704 -66.33811,0.32111
+ -132.71013,-0.65448 -199.027348,0.50195 -36.88034,3.81003 -68.1757706,37.6184 -67.9770919,74.92075
+ -0.11974,15.728089 -1.28154,31.763209 1.8410828,47.270329 6.7502267,29.04757 31.6537591,53.16732
+ 61.1340561,58.28353 -1.435617,13.25989 8.021284,27.64848 21.970703,28.58594 8.923315,0.71852
+ 18.134142,0.91421 26.863278,-0.81836 10.98672,-3.32996 18.17661,-15.07973 17.4336,-26.23829
+ 18.89059,-0.47804 37.90443,-0.0675 56.8457,-0.21875 26.9694,0 53.9388,0 80.9082,0 27.97776,14.19909
+ 62.65545,14.19634 90.64844,0.0488 4.99941,0.68075 11.22902,-1.39507 15.41211,0.61328 -1.17524,14.51864
+ 12.11467,28.65073 26.91406,26.78125 11.25833,0.67766 24.8809,1.42157 32.9043,-8.14843 5.01958,-5.52579
+ 6.70326,-13.30572 6.33398,-20.5918 36.54533,-6.13315 65.47804,-41.8142 63.06646,-78.96801 0.67317,-21.787919
+ 1.56059,-45.412209 -10.89409,-64.472679 -14.51203,-24.19526 -42.66168,-39.44002 -70.93204,-37.57898
+ -21.46793,-0.43562 -43.31328,1.1073 -64.52939,-0.85142 -14.0115,-6.6728004 -29.57625,-10.0359804
+ -45.0918,-9.7832104 z m 3.28711,16.4785204 c 39.4604,0.0658 75.89146,31.41223 82.27149,70.02344
+ 6.79984,34.983409 -11.44403,73.520729 -43.13477,90.267569 -32.78726,18.23663 -76.56419,11.75134
+ -102.39453,-15.76172 -24.88947,-25.53578 -31.3338,-67.053579 -14.18555,-98.699209 14.6625,-28.09909
+ 45.60502,-46.90957 77.44336,-45.83008 z m 112.33399,10.67383 c 32.13876,-0.0197 60.69034,29.32254
+ 59.44336,61.44922 -0.69558,2.25642 1.8751,7.80675 -2.23242,6.70117 -7.08467,0.35634 -15.90425,-2.42077
+ -21.81446,2.685539 -5.01715,5.68783 0.85519,15.60252 8.3711,13.64453 5.1198,0.31176 11.40865,-0.61399
+ 15.82226,0.44532 1.63171,29.03662 -19.55265,57.82899 -48.56054,63.03125 -18.48076,3.19513 -37.49076,0.17533
+ -56.08985,1.51367 31.99079,-28.68807 42.17176,-78.68532 23.4213,-117.454169 -5.58165,-12.04358
+ -13.53357,-22.98632 -23.27481,-32.00481 14.97133,-0.009 29.94281,0.0167 44.91406,-0.0117 z m -350.277346,0.01
+ c 55.645176,0.005 111.290366,6.4e-4 166.935546,0.002 -31.38309,28.43673 -41.74351,77.417349
+ -23.81363,115.925109 5.60217,12.57373 13.77638,23.99845 23.87613,33.35223 -58.15499,-0.33709
+ -116.36174,0.74961 -174.484374,-0.57422 -13.072871,-1.8228 -25.454131,-8.10601 -34.722656,-17.49219
+ 15.266585,-0.30705 30.7027,0.87778 45.873047,-0.61523 7.727176,-2.72104 5.50485,-15.99864 -2.785156,-15.81641
+ -18.232389,-0.0455 -36.464843,-0.018 -54.697266,-0.0234 -4.916353,-9.88878 -6.381031,-20.98578
+ -6.056641,-31.86523 62.408265,-0.23294 124.883136,0.48231 187.249996,-0.36914 8.05374,-1.95579
+ 6.99391,-15.613319 -1.40039,-16.021479 -61.9353,-0.24209 -123.871107,-0.0443 -185.806637,-0.10547
+ -0.09346,-6.63177 0.09723,-13.34266 1.712891,-19.8086 33.89003,-0.3703 67.912224,0.78478 101.722656,-0.58203
+ 7.88019,-2.58382 5.74789,-16.0619 -2.61914,-15.88672 -30.782327,-0.17583 -61.56644,0.22381 -92.347657,-0.17773
+ 10.587263,-18.07301 30.707654,-29.79202 51.363281,-29.94141 z M 386.96094,195.31611 c 10.51484,1.13977
+ 21.75903,-0.14334 32.07422,0.61524 0.87866,6.65214 -5.30372,12.67167 -11.91993,10.71484 -6.64769,-0.33544
+ -16.41047,2.75342 -20.41015,-4.45117 -0.17534,-1.17232 -2.59486,-6.95399 0.25586,-6.87891 z
+ m -310.761721,0.11524 c 10.789569,0.85487 22.190459,-0.15849 32.767581,0.48632 0.89634,6.67101
+ -5.30259,12.66113 -11.912112,10.72657 -6.714172,-0.31317 -17.086942,2.86291 -20.597657,-4.99414
+ -0.207806,-1.53014 -1.947751,-5.29317 -0.257812,-6.21875 z"/>
</g>
</svg>
diff --git a/src/icons/refresh_icon.svg b/src/icons/refresh_icon.svg
new file mode 100644
index 0000000..1660754
--- /dev/null
+++ b/src/icons/refresh_icon.svg
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 279.881 279.881" style="enable-background:new 0 0 279.881 279.881;" xml:space="preserve" width="512px" height="512px">
+<g>
+ <path d="M153.905,130.755c2.562-5.39,5.695-12.222,8.169-18.4c2.241-5.57-0.315-13.201-5.314-16.529 C124.589,74.369,15.465,12.559,3.118,151.467c-0.533,5.983-1.594,6.054-2.187,0.076C-1.157,130.63-2.13,84.415,25.457,59.531 c4.46-4.019,12.319-9.801,17.345-13.086c17.884-11.71,62.767-31.857,127.318,2.594c5.303,2.828,10.476,0.598,11.727-5.276 l4.493-21.142c1.246-5.874,4.775-6.467,7.887-1.327l52.917,87.563c3.106,5.14,0.865,10.334-5.009,11.607l-82.375,17.764 C153.878,139.496,151.327,136.178,153.905,130.755z M236.247,239.357c-17.884,11.694-62.761,31.802-127.318-2.622 c-5.303-2.828-11.047-0.756-12.994,4.928l-5.466,15.958c-1.947,5.684-5.793,5.978-8.588,0.658l-42.256-80.444 c-2.796-5.319-0.402-11.052,5.347-12.804l69.832-21.332c5.744-1.751,9.1,1.517,7.5,7.316c-1.795,6.489-4.117,14.947-6.081,22.175 c-1.572,5.798,1.137,13.353,6.206,16.589c32.553,20.766,142.743,80.319,154.741-56.653c0.522-5.983,1.496-6.032,2.007-0.049 c1.806,21.153,2.197,68.157-25.58,93.198C249.133,230.29,241.279,236.072,236.247,239.357z" fill="#00942c"/>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/src/icons/screen_icon.svg b/src/icons/screen_icon.svg
index f2ca511..d4f0ba4 100644
--- a/src/icons/screen_icon.svg
+++ b/src/icons/screen_icon.svg
@@ -1,44 +1,9 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="612px" height="612px" viewBox="0 0 612 612" style="enable-background:new 0 0 612 612;" xml:space="preserve">
-<g>
+<?xml version="1.0" encoding="utf-8"?>
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="612" height="612">
<path d="M578.766,51.487v-0.895h-2.996H35.93h-2.996v0.895C15.272,52.701,2.095,66.753,0,83.808v3.002v355.724
c0,6.898,1.795,12.712,4.791,17.949c6.893,12.137,17.068,18.269,31.14,18.269h197.012v49.695h-37.425
c-9.281,0-16.467,7.218-16.467,16.48c0,9.262,7.186,16.479,16.467,16.479h220.666c9.281,0,16.768-7.218,16.768-16.479
c0-9.263-7.486-16.48-16.768-16.48h-37.425v-49.695H575.77c14.078,0,24.343-6.132,31.14-18.269
c3.085-5.493,5.091-11.37,5.091-17.949V86.811v-3.002C609.905,66.753,595.833,52.701,578.766,51.487z M578.766,86.811v355.724
c0,2.108-0.895,3.002-2.996,3.002H35.93c-2.095,0-2.996-0.894-2.996-3.002V86.811v-3.002h545.831V86.811z"/>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
-<g>
-</g>
</svg>
diff --git a/src/main.cpp b/src/main.cpp
index 2a85617..6c7f492 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -20,23 +20,34 @@ bool showGui() { return _showGui; }
bool backgroundMode() { return _backgroundMode; }
}
-static void parseCommandLine(const QApplication &a);
+static void parseCommandLine(const QCoreApplication &a);
int main(int argc, char *argv[])
{
- QApplication a(argc, argv);
+ QCoreApplication *a;
+ bool gui = true;
+ for (int i = 0; i < argc; ++i) {
+ if (strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "--wakeup") == 0) {
+ gui = false;
+ }
+ }
+ if (gui) {
+ a = new QApplication(argc, argv);
+ } else {
+ a = new QCoreApplication(argc, argv);
+ }
QCoreApplication::setApplicationName("BeamerGUI XP - Home Edition");
QCoreApplication::setApplicationVersion("2.0");
// System strings
- QTranslator *qtTranslator = new QTranslator(&a);
+ QTranslator *qtTranslator = new QTranslator(a);
qtTranslator->load(QLocale::system(), "qt", "_", QLibraryInfo::location(QLibraryInfo::TranslationsPath));
- a.installTranslator(qtTranslator);
+ a->installTranslator(qtTranslator);
// App specific
- QTranslator *translator = new QTranslator(&a);
+ QTranslator *translator = new QTranslator(a);
translator->load(QLocale::system(), ":");
- a.installTranslator(translator);
+ a->installTranslator(translator);
- parseCommandLine(a);
+ parseCommandLine(*a);
if (_wakeup) {
return Bus::inst()->registerService() ? 0 : 1;
@@ -60,10 +71,10 @@ int main(int argc, char *argv[])
}
if (w == nullptr)
return 0;
- return a.exec();
+ return a->exec();
}
-static void parseCommandLine(const QApplication &a)
+static void parseCommandLine(const QCoreApplication &a)
{
// Command line
QCommandLineParser parser;
diff --git a/src/widget.cpp b/src/widget.cpp
index bc4869f..49e5285 100644
--- a/src/widget.cpp
+++ b/src/widget.cpp
@@ -68,6 +68,9 @@ static void addBoldListener(QComboBox *combo)
});
}
+static const QString resetButtonStyle("padding: 2px; margin: 0 0 1px 1px;");
+static const QString resetButtonHotStyle(resetButtonStyle + "background-color: #f99;");
+
/*
* Main widget
*/
@@ -77,64 +80,92 @@ Widget::Widget(QWidget *parent) :
_ui(new Ui::Widget),
_popupCount(0),
_iProjector(QIcon(":projector")),
- _iScreen(QIcon(":screen"))
+ _iScreen(QIcon(":screen")),
+ _lastScreenCount(0),
+ _isDbus(true)
{
_ui->setupUi(this);
+ // Add refresh button
+ _ui->btnReload->setStyleSheet(resetButtonStyle);
+ _ui->tabWidget->setCornerWidget(_ui->btnReload);
+ connect(_ui->btnReload, &QPushButton::clicked, [=](bool) {
+ _ui->btnReload->setStyleSheet(resetButtonStyle);
+ ScreenSetup::inst()->initModes();
+ initControls();
+ });
setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
QTimer *top = new QTimer(this);
connect(top, &QTimer::timeout, [=]() {
+ if (this->isHidden())
+ return;
// Move window to current screen
- QRect win = this->geometry();
- QPoint cursor = QCursor::pos();
- const QScreen *winScreen = nullptr, *mouseScreen = nullptr;
- //qDebug() << "Mouse at" << cursor << " window at" << win;
- for (auto screen : _qtScreens) {
- QRect geo = screen->geometry();
- if (geo.contains(win)) {
- winScreen = screen;
- //qDebug() << "Window on screen" << geo;
- }
- if (geo.contains(cursor)) {
- mouseScreen = screen;
- //qDebug() << "Mouse on screen" << geo;
- }
- }
- if (mouseScreen != nullptr && mouseScreen != winScreen) {
- QPoint offset = mouseScreen->geometry().topLeft();
- QSize spacing = (mouseScreen->size() - this->size()) / 2;
- offset.rx() += spacing.width();
- offset.ry() += spacing.height();
- this->move(offset);
+ if (qApp->mouseButtons() == Qt::NoButton) {
+ updateWindowPlacement();
}
// Raise window if appropriate
- if (_popupCount > 0)
- return;
- auto combos = this->findChildren<QComboBox*>();
- for (auto combo : combos) {
- if (combo->view()->isVisible())
- return;
+ if (_popupCount == 0) {
+ bool ok = true;
+ auto combos = this->findChildren<QComboBox*>();
+ for (auto combo : combos) {
+ if (combo->view()->isVisible()) {
+ ok = false;
+ break;
+ }
+ }
+ if (ok) {
+ raise();
+ }
}
- raise();
});
top->start(1000);
addBoldListener(_ui->cboCloneResolution);
addBoldListener(_ui->cboDualLeft);
addBoldListener(_ui->cboDualRight);
connectButtons();
- auto fun = [this](const QScreen *scrn) {
- qDebug() << "QT SEES SCREEN" << scrn->geometry();
- _qtScreens.append(scrn);
- /*
- connect(scrn, &QScreen::geometryChanged, [this](const QRect &geom) {
-
- });
- */
+ // Handle screens on Qt level
+ // Timer
+ QTimer *t = new QTimer(this);
+ t->setSingleShot(true);
+ // Worked fine
+ connect(t, &QTimer::timeout, [=]() {
+ int currentCount = ScreenSetup::inst()->queryCurrentOutputCount();
+ qDebug() << "Timeout. Dbus:" << _isDbus << "old count:" << _lastScreenCount << "new count:" << currentCount;
+ if (_isDbus && _lastScreenCount >= currentCount)
+ return; // Ignore dbus events if the screen count didn't change (or decreased)
+ if (this->isHidden()) {
+ ScreenSetup::inst()->initModes();
+ _isDbus = true;
+ this->show();
+ } else {
+ if (currentCount > _lastScreenCount) {
+ ScreenSetup::inst()->initModes();
+ initControls();
+ } else {
+ _ui->btnReload->setStyleSheet(resetButtonHotStyle);
+ }
+ }
+ });
+ auto popupGui = [=]() {
+ if (this->isHidden()) {
+ t->start(1000);
+ } else {
+ _ui->btnReload->setStyleSheet(resetButtonHotStyle);
+ }
};
for (auto scrn : QGuiApplication::screens()) {
- fun(scrn);
+ _qtScreens.append(scrn);
}
- connect(qApp, &QGuiApplication::screenAdded, fun);
- connect(qApp, &QGuiApplication::screenRemoved, [this](const QScreen *scrn) {
+ connect(qApp, &QGuiApplication::screenAdded, [=](const QScreen *scrn) {
+ qDebug() << "QT SEES SCREEN" << scrn->geometry();
+ _qtScreens.append(scrn);
+ if (CommandLine::backgroundMode()) {
+ qDebug() << "Qt setting FALSE";
+ _isDbus = false;
+ popupGui();
+ }
+ });
+ connect(qApp, &QGuiApplication::screenRemoved, [=](const QScreen *scrn) {
+ qDebug() << "Qt lost screen" << scrn->geometry();
_qtScreens.removeAll(scrn);
});
_ui->btnExit->setVisible(CommandLine::backgroundMode());
@@ -144,28 +175,23 @@ Widget::Widget(QWidget *parent) :
qDebug() << "WARNING: CANNOT CONNECT TO DBUS FOR LISTENING";
// TODO: GUI feedback
} else {
- // Worked fine
- // Timer
- QTimer *t = new QTimer(this);
- t->setSingleShot(true);
- connect(t, &QTimer::timeout, [=]() {
- if (this->isHidden()) {
- ScreenSetup::inst()->initModes();
- this->show();
- } else {
- // TODO: Flash button
- }
- });
// GUI popup logic
connect(Bus::inst(), &Bus::serviceConnected, [=]() {
qDebug() << "\\o/ Received DBus connect notification \\o/";
- if (this->isHidden()) {
- t->start(1500);
- } else {
- // TODO: Flash button
- }
+ popupGui();
});
}
+ // Xlib
+ connect(ScreenSetup::inst(), &ScreenSetup::outputConfigChanged, [=](ConnectionEvent type) {
+ if (type == ConnectionEvent::Disconnected) {
+ if (!this->isHidden()) {
+ _ui->btnReload->setStyleSheet(resetButtonHotStyle);
+ }
+ } else {
+ _isDbus = false;
+ popupGui();
+ }
+ });
}
}
@@ -178,6 +204,7 @@ void Widget::showEvent(QShowEvent *event)
{
QWidget::showEvent(event);
initControls(true);
+ updateWindowPlacement(true);
}
static void fillCombo(QComboBox *combo, const ResolutionVector &resolutions, const QSize &preselected, const QSize &preferred = QSize())
@@ -223,6 +250,8 @@ void Widget::comboBold(int index)
void Widget::initControls(bool jumpToTab)
{
+ _lastScreenCount = ScreenSetup::inst()->getOutputCount();
+ _ui->btnReload->setStyleSheet(resetButtonStyle);
//
ScreenMode currentOpMode = ScreenSetup::inst()->getCurrentMode();
_ui->tabWidget->setTabEnabled(1, CommandLine::testMode() || ScreenSetup::inst()->getOutputCount() == 2 || currentOpMode == ScreenMode::Dual);
@@ -265,13 +294,24 @@ void Widget::initControls(bool jumpToTab)
QSize preferredClone;
for (auto screen : screenList) {
if (!screen.preferredResolution.isEmpty()) {
- preferredClone = screen.preferredResolution;
+ if (screen.isProjector // Projector always overrides
+ || preferredClone.isEmpty() // Have no preferred yet
+ || screen.preferredResolution.width() < preferredClone.width() // For normal screens,
+ || screen.preferredResolution.height() < preferredClone.height()) { // smallest wins
+ preferredClone = screen.preferredResolution;
+ }
if (screen.isProjector)
break;
}
}
fillCombo(_ui->cboCloneResolution, modes, screenList[0].currentResolution, preferredClone);
// Dual
+ _ui->dualContainer->takeAt(0);
+ _ui->dualContainer->takeAt(1);
+ _ui->dualContainer->takeAt(2);
+ _ui->dualContainer->addLayout(_ui->dualLeft);
+ _ui->dualContainer->addWidget(_ui->btnDualSwap);
+ _ui->dualContainer->addLayout(_ui->dualRight);
if (screenList.size() >= 2) {
auto lists = QList<QComboBox*>({_ui->cboDualLeft, _ui->cboDualRight});
int j = 0;
@@ -575,4 +615,30 @@ void Widget::connectButtons() {
}
+void Widget::updateWindowPlacement(bool force)
+{
+ QRect win = this->geometry();
+ QPoint cursor = QCursor::pos();
+ const QScreen *winScreen = nullptr, *mouseScreen = nullptr;
+ //qDebug() << "Mouse at" << cursor << " window at" << win;
+ for (auto screen : _qtScreens) {
+ QRect geo = screen->geometry();
+ if (geo.contains(win)) {
+ winScreen = screen;
+ //qDebug() << "Window on screen" << geo;
+ }
+ if (geo.contains(cursor)) {
+ mouseScreen = screen;
+ //qDebug() << "Mouse on screen" << geo;
+ }
+ }
+ if (mouseScreen != nullptr && (force || mouseScreen != winScreen)) {
+ QPoint offset = mouseScreen->geometry().topLeft();
+ QSize spacing = (mouseScreen->size() - this->size()) / 2;
+ offset.rx() += spacing.width();
+ offset.ry() += spacing.height();
+ this->move(offset);
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
diff --git a/src/widget.h b/src/widget.h
index f784ce9..ddf14fb 100644
--- a/src/widget.h
+++ b/src/widget.h
@@ -34,10 +34,13 @@ private:
QList<const QScreen *> _qtScreens;
bool _popupCount;
QIcon _iProjector, _iScreen;
+ int _lastScreenCount;
+ bool _isDbus;
void initControls(bool jumpToTab = false);
void connectButtons();
bool keepResolution();
+ void updateWindowPlacement(bool force = false);
};
#endif // WIDGET_H
diff --git a/src/widget.ui b/src/widget.ui
index a0be031..fe6f67b 100644
--- a/src/widget.ui
+++ b/src/widget.ui
@@ -22,11 +22,28 @@
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
+ <widget class="QPushButton" name="btnReload">
+ <property name="text">
+ <string notr="true"/>
+ </property>
+ <property name="icon">
+ <iconset resource="icons.qrc">
+ <normaloff>:/refresh</normaloff>:/refresh</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
- <number>2</number>
+ <number>1</number>
</property>
<widget class="QWidget" name="tabClone">
<attribute name="title">
@@ -109,7 +126,7 @@ border: 2px solid black;
<item>
<layout class="QHBoxLayout" name="dualContainer">
<item>
- <layout class="QVBoxLayout" name="verticalLayout_2">
+ <layout class="QVBoxLayout" name="dualLeft">
<item>
<widget class="QWidget" name="wDualLeft" native="true">
<layout class="QVBoxLayout" name="verticalLayout_4">
@@ -152,7 +169,7 @@ border: 2px solid black;
</widget>
</item>
<item>
- <layout class="QVBoxLayout" name="verticalLayout_3">
+ <layout class="QVBoxLayout" name="dualRight">
<item>
<widget class="QWidget" name="wDualRight" native="true">
<property name="margin" stdset="0">
diff --git a/src/xprivate.cpp b/src/xprivate.cpp
index 120fb66..ce7ce8c 100644
--- a/src/xprivate.cpp
+++ b/src/xprivate.cpp
@@ -82,9 +82,11 @@ void XPrivate::updateScreenResources()
_modeMap.insert(
_screenResources->modes[i].id,
&_screenResources->modes[i]);
+ /*
qDebug() << _screenResources->modes[i].id << "\t"
<< _screenResources->modes[i].width << "x"
<< _screenResources->modes[i].height;
+ */
}
/*
@@ -190,25 +192,23 @@ void XPrivate::updateScreenResources()
qSort(screens.begin(), screens.end(), xRectLessThan);
int endX = -0xffff;
qDebug() << "From left to right";
- for (OutputInfo* output : screens) {
- if (output->mode == nullptr) {
- qDebug() << "(Ignoring" << output->outputName << "since it's disconnected)";
- }
- if (output->crtc->x >= endX) {
- QSize res(0, 0);
- if (_modeMap.contains(output->crtc->mode)) {
- auto mode = _modeMap.value(output->crtc->mode);
- res = QSize(int(mode->width), int(mode->height));
- }
- _resolutions.append(res);
- endX = -0xffff; // Reset
- }
- output->position = _resolutions.size() - 1;
- qDebug() << "Screen (" << output->crtc->x << "," << output->crtc->y << ") @" << output->crtc->width << "x" << output->crtc->height << "as screen" << output->position;
- if (output->crtc->x + int(output->crtc->width) > endX) {
- endX = output->crtc->x + int(output->crtc->width);
- }
- }
+ for (OutputInfo* output : screens) {
+ if (output->mode == nullptr) {
+ qDebug() << "(Ignoring" << output->outputName << "since it's disconnected)";
+ continue;
+ }
+ if (output->crtc->x >= endX) {
+ QSize res(0, 0);
+ res = QSize(int(output->mode->width), int(output->mode->height));
+ _resolutions.append(res);
+ endX = -0xffff; // Reset
+ }
+ output->position = _resolutions.size() - 1;
+ qDebug() << "Screen (" << output->crtc->x << "," << output->crtc->y << ") @" << output->mode->width << "x" << output->mode->height << "as screen" << output->position;
+ if (output->crtc->x + int(output->crtc->width) > endX) {
+ endX = output->crtc->x + int(output->mode->width);
+ }
+ }
qDebug() << "Loaded.";
}
diff --git a/src/xx.cpp b/src/xx.cpp
index 2a8cdc5..d9c05d6 100644
--- a/src/xx.cpp
+++ b/src/xx.cpp
@@ -2,7 +2,7 @@
#include "xprivate.h"
#include "cvt.h"
#include <QDebug>
-
+#include <QSocketNotifier>
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
@@ -36,10 +36,58 @@ static ScreenInfo initScreenInfo(const OutputInfo *oi, const ModeMap &om)
ScreenSetup * ScreenSetup::_instance = nullptr;
+static int errorHandlerX(Display*)
+{
+ exit(1);
+}
+
ScreenSetup::ScreenSetup() : a(new XPrivate())
{
- /* Get informations about Xserver */
+ int event_base_return, error_base_return;
+ if (!XRRQueryExtension(a->_display, &event_base_return, &error_base_return)) {
+ qDebug() << "No XRANDR extension found";
+ exit(1);
+ }
updateScreenResources();
+ //XSelectInput(a->_display, DefaultRootWindow(a->_display), StructureNotifyMask);
+ XRRSelectInput(a->_display, DefaultRootWindow(a->_display), RROutputChangeNotifyMask);
+ //XSync(a->_display, False);
+ XSetIOErrorHandler((XIOErrorHandler) errorHandlerX);
+ _socketNotifier = new QSocketNotifier(qintptr(ConnectionNumber(a->_display)), QSocketNotifier::Read);
+ connect(_socketNotifier, &QSocketNotifier::activated, [=](int) {
+ XEvent ev;
+ qDebug() << "Socket Event";
+ while (XPending(a->_display) > 0) {
+ XNextEvent(a->_display, &ev);
+ if (ev.type - event_base_return != RRNotify) {
+ qDebug() << "Received unknown X event";
+ continue;
+ }
+ qDebug() << "Got Change Event";
+ XRROutputChangeNotifyEvent *oce = reinterpret_cast<XRROutputChangeNotifyEvent*>(&ev);
+ XRRScreenResources *sr = XRRGetScreenResources(oce->display, oce->window);
+ if (sr == nullptr) {
+ emit outputConfigChanged(ConnectionEvent::Unknown);
+ continue;
+ }
+ XRROutputInfo *oi = XRRGetOutputInfo(a->_display, sr, oce->output);
+ if (oi == nullptr) {
+ XRRFreeScreenResources(sr);
+ emit outputConfigChanged(ConnectionEvent::Unknown);
+ continue;
+ }
+ if (oi->connection == RR_Connected) {
+ emit outputConfigChanged(ConnectionEvent::Connected);
+ } else if (oi->connection == RR_Disconnected) {
+ emit outputConfigChanged(ConnectionEvent::Disconnected);
+ } else {
+ emit outputConfigChanged(ConnectionEvent::Unknown);
+ }
+ XRRFreeOutputInfo(oi);
+ XRRFreeScreenResources(sr);
+ }
+ });
+
}
@@ -337,11 +385,36 @@ ResolutionVector ScreenSetup::getCommonModes() const
return ret;
}
+/**
+ * Return number of connected (no active) outputs according to last query
+ */
int ScreenSetup::getOutputCount() const
{
return a->_outputMap.size();
}
+/**
+ * Query currently connected number of outputs
+ */
+int ScreenSetup::queryCurrentOutputCount() const
+{
+ auto sr = XRRGetScreenResourcesCurrent(a->_display, DefaultRootWindow(a->_display));
+ if (sr == nullptr)
+ return 0;
+ int count = 0;
+ for (int i = 0; i < sr->noutput; ++i) {
+ XRROutputInfo* info = XRRGetOutputInfo(a->_display, sr, sr->outputs[i]);
+ if (info == nullptr)
+ continue;
+ if (info->connection != RR_Disconnected) {
+ count++;
+ }
+ XRRFreeOutputInfo(info);
+ }
+ XRRFreeScreenResources(sr);
+ return count;
+}
+
const ResolutionVector &ScreenSetup::getVirtualResolutions() const
{
return a->_resolutions;
diff --git a/src/xx.h b/src/xx.h
index a17d4b7..ff0ea11 100644
--- a/src/xx.h
+++ b/src/xx.h
@@ -7,6 +7,7 @@
struct ScreenInfo;
class XPrivate;
+class QSocketNotifier;
typedef QVector<QSize> ResolutionVector;
@@ -31,8 +32,16 @@ struct ScreenInfo
ResolutionVector modes;
};
-class ScreenSetup
+enum class ConnectionEvent
{
+ Connected,
+ Disconnected,
+ Unknown,
+};
+
+class ScreenSetup : public QObject
+{
+ Q_OBJECT
public:
void updateScreenResources();
void initModes();
@@ -44,6 +53,7 @@ public:
bool setCustom(const QList<QPair<QSize, QList<QString>>> &list);
ResolutionVector getCommonModes() const;
int getOutputCount() const;
+ int queryCurrentOutputCount() const;
QMap<QString, ScreenInfo> getScreenPositions() const;
const ResolutionVector &getVirtualResolutions() const;
@@ -59,6 +69,10 @@ private:
static ScreenSetup * _instance;
XPrivate *a;
+ QSocketNotifier *_socketNotifier;
+signals:
+ void outputConfigChanged(ConnectionEvent event);
+
};
///////////////////////////////////////////////////////////////////////////
diff --git a/udev/99-beamergui.rules b/udev/99-beamergui.rules
new file mode 100644
index 0000000..06364e2
--- /dev/null
+++ b/udev/99-beamergui.rules
@@ -0,0 +1,3 @@
+# Tell beamergui to show up
+#
+SUBSYSTEM=="drm", ACTION=="change", RUN+="/opt/openslx/bin/beamergui -w"