~g)zXjWbCXIE$
z9rgOf!x73lCA-pIX*OnNXK6_im6`Sicqfy5G|VYFrRPB)bz%Mei}ox~eu?)fIhB@v
zlg8vTzgC(3dAasAI)AKgD3)IZloA-B^gDsu?nu^aa?p$3xvl)+jVwu-;3}N*PDnId
zx)+F%J1JLagwV$Pto2DxPK$QBamep_xjyuz?0AC#<(_j>*Q?*mOFl0xjt>8N&E5)(
zNE2U@aOXGv7)3cw}4V#F3GB@z7Js@Eu%=r?DL`q9)R|$m|4e#3C*AUpg$xiWo&V1d+vB2(QN))Xck4_uYqK
zd=Qy~cgTh#<6&?`1niYHM;dmMSUok6}dJC7Q-kWWMl
zU4_a>Zap1kU;tHYG5y*fluRkRI%=fP+<5X-jDC0R#?qR
zJ--5#iAOMm`;k}L5$xCZ{~;Y^AjCJ(hRaYlI;afcAD@MF|U&!VjoAtwQO0^0{MalfUuR>YsBAN)*fL5)xZ4U2P
zz){<&rtGO{|L^j8X7^w#v7TUiy!YEm|Dw2?s3BBT+71=rrA85ZDb+S8^&9;Q4R|MU
z6S3Jpw+>aH+N$}j-~Ykx*jBw?|4=AyuU*D*HPJ_`B5olrwKa6^CA5e0n~JcP*f8&;
z>PI!xL)_+{FU0MBUu+`6?s)O31^J4_CxTt^ozA1ljCCc3od=TfSiU3J>^>Ka2HbGj
z*?_yUq9l<2x$@hpXgrMzKoNKIq8^f
zPC2_WiO1q;Cx5cG)h%6mC=lq+Z*8n_|EMb{aO;;h2lAB-zlOar6Wrzx+ZXo+O+FM)
KyC)lK1OEZZu-It;
delta 3815
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
H(;IpV%%8O2
delta 3940
zcmai#du$ZP8NkOFlce}bVoCzog8|#5a4yf5l(Z=}$|mm$@$K@y~A}Y
zaTrhutre#n7$vGgBHE-uCAB%fFn&~Nsi>5qT~(FZG>V#k8kCej(yEUrjnv<_yFS}N
zN=N?gH#0l?y=Q%O&qr;kcNWb*qZkK~Wk`OmQYrY~JboDexlO4hIZAy5Z@@)&D7BpZ
zk3Xl>o$&63?7?-AN9qB{pL&EJQLzUufKS4^U=YfC-|_ZSs)q@GD$P#`JO>xU0k{NS
zgE9Cn+yQszD^&>3LUH63SPg#-E8tCdKP)cr3^%~NtefED@FKhdKY@i3>SeSMoVo^Y
zhc+yRe}Z?z_aQpf{36ex5-1Vf3+27_a5dZtKM%hRCDKkP`g-6}cm@)K8i1mILe`S%
z>r6!9TmFN0;bzuT^jON7Z5|=PKcRSOdkuO;A$4&F3!2
zp9=Alk_ZnmL6>?CYWOnzB76gGh5vw(fpu7u6yFEs`2i@AJqz!F7oe2rDintnVpaB+
zLMiDMDE8`MHEg|;{6EFyIX0evAHy%h2J$D0Pe5s^^H6%>BHRyu1I3|=QjaxI3~qyR
z{xK*S-2*Lnz~6Tuv8X>oRH&P!b{)_bq
zco-fo_Y{5tx3JFFN__>^LRqI^1P((nymAGN4L873@Ne){0!mRoY1XP$N})=n>Y0c~
z?f%AL_z>$Cp_Je~C<0Yj7W)9wgtI^$2;E6#fy0;Y~;|YA-L5G}Q$~;aPY)dmZy6*aJMi5dyZL<(`5Gcl)+4jWP8Pe6hY(uAy)9po`pb|sNs6~3Qd1cu
z!M#dk(d~~sn2$Vy$hZx;19=R=|LmB@tQeuu-KNd_f!yLKO3BpZw-5AKKL8_cWxwV)KCkKOTge)k~rkpu3I_tBEx%9BRe
zo4LBc$V)|HmKoPZM~7*|Egdo9t!8|!Zb`-yZL{{Rb|Vro;{jb8izec+h^0ejN1{!4
zwwX~Kj_S^E$h3lSlT~{xWCm1iti3rLHF?0PP}u5-7+u1I5e=F;5z|JnEo>e#tF)nm
zvG$f&JYh6POdVk_qGK(-ej^&vR`|PSAiXMoB2}A=A2LJJ>QtTCVk9F8RTsA8-H=S?
z*tumxTWuH$Cf#@3qoO=}ED>vM#fND(Emaqb8VOVFh`Rbu6;v-atb}gd-sncDEutfg
zXltgjU|-HAvqO_KeJC7HB#p?ln>tEn-3LK4njohH*A+{~IcIhTGT$qFDrZHrndp?<
zB|2leBW{Mw7INnX>gLM|r2kO#mz179))FxiT2d37lMpMQ8eNY}OSeW0%YtM&>u$Kc
z-3)~ZDAMH>t|O9cZN*MFx>ko*{;sl*d#dKyh_0~z=b=yM}JZ*M0$Ba1D_A3-fca(eGU<{V3sbM!qxQJA2ka|MhMg1k&|2*r^*5b9`-;=!Jj3#GK->P=LA#&rzL|65
z_K-c1J@tY;*v6P)2G=P
zvWLaGb4-gyHYVjLswOqh#@LX<{Q+g4L&Ir%kQa~Hmr*jL?Gbe2^x!O|SRF)9w>^b3
zLryPlpG4n)Y)?A%-A=Eak$|;pX52Y0ezAeau2B|!I6UF>&W&eOd;U(^BY4{!&1Z
zZb3(+INx`RepKR?g7#A_ze*!+2FZq9abw;-NZZid$(L1LxT&?NX
zsx~f{OYWynx=q5RbNkRrZPG_p-j$*o=%ZfBOfSvq+RyG;O`}R-$MJ5$jc<}$^zF&Re=Q+o<<=UeDO~t}-PbNjs}bi{;}oMos!9
da_5;qx@pbMs+S1fz2%>kFXve1`87Y!`5#8+!~g&Q
diff --git a/ui/po/mo/zh_CN/LC_MESSAGES/breezydesktop.mo b/ui/po/mo/zh_CN/LC_MESSAGES/breezydesktop.mo
index 9a1698ad290d4175381f4b241763481116c3756b..2373235cf0ca4467c57b93ee006bae3ee87c3495 100644
GIT binary patch
delta 2521
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
diff --git a/ui/po/pl.po b/ui/po/pl.po
index 0b599c8..2bb7084 100644
--- a/ui/po/pl.po
+++ b/ui/po/pl.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-10-22 13:27-0700\n"
+"POT-Creation-Date: 2025-03-05 12:28-0800\n"
"PO-Revision-Date: 2024-08-16 10:26-0700\n"
"Last-Translator: \n"
"Language-Team: Polish \n"
@@ -18,16 +18,58 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n"
-#: src/connecteddevice.py:17
+#: src/connecteddevice.py:23
msgid ""
"Switches your glasses into side-by-side mode and doubles the width of the "
"display."
msgstr ""
-#: src/connecteddevice.py:18
+#: src/connecteddevice.py:24
msgid "This feature is not currently supported for your device."
msgstr ""
+#: src/connecteddevice.py:124
+msgid "Set Focused Display Distance"
+msgstr ""
+
+#: src/connecteddevice.py:125
+msgid "Use a closer value so the display zooms in when you look at it."
+msgstr ""
+
+#: src/connecteddevice.py:132
+msgid "Set All Displays Distance"
+msgstr ""
+
+#: src/connecteddevice.py:133
+msgid "Use a farther value so the displays are zoomed out when you look away."
+msgstr ""
+
+#: src/connecteddevice.py:231
+msgid ""
+"Unable to add virtual displays on this machine. xdg-desktop-portal is "
+"required."
+msgstr ""
+
+#: src/connecteddevice.py:265
+msgid "Focused display"
+msgstr ""
+
+#: src/connecteddevice.py:271
+msgid "All displays"
+msgstr ""
+
+#: src/displaydistancedialogcontent.py:41
+msgid "closer"
+msgstr ""
+
+#: src/displaydistancedialogcontent.py:45
+msgid "fullscreen"
+msgstr ""
+
+#: src/displaydistancedialogcontent.py:48
+msgid "farther"
+msgstr ""
+
#: src/licensedialogcontent.py:63
msgid "Paid Tier Status"
msgstr ""
@@ -36,7 +78,7 @@ msgstr ""
msgid "Feature Availability"
msgstr ""
-#: src/licensefeaturerow.py:15 src/shortcutdialog.py:107
+#: src/licensefeaturerow.py:15 src/shortcutdialog.py:104
msgid "Disabled"
msgstr ""
@@ -165,173 +207,235 @@ msgid "Enables the Breezy Desktop XR effect."
msgstr ""
#: src/gtk/connected-device.ui:55
-msgid "Widescreen mode"
+msgid "Zoom on focus"
msgstr ""
-#: src/gtk/connected-device.ui:66
+#: src/gtk/connected-device.ui:56
+msgid ""
+"Automatically move a display closer when you look at it.\n"
+"Set your preferred focused and unfocused distances in the Adjustments "
+"section.\n"
+" "
+msgstr ""
+
+#: src/gtk/connected-device.ui:69
msgid "Follow mode"
msgstr ""
-#: src/gtk/connected-device.ui:67
-msgid "Keep the virtual display near the center of your view."
+#: src/gtk/connected-device.ui:70
+msgid "Keep the focused display near the center of your view."
msgstr ""
-#: src/gtk/connected-device.ui:77
-msgid "Curved display"
+#: src/gtk/connected-device.ui:80 src/gtk/no-device.ui:34
+msgid "Disable physical displays"
msgstr ""
-#: src/gtk/connected-device.ui:78
-msgid "Switch between flat and curved displays."
+#: src/gtk/connected-device.ui:81 src/gtk/no-device.ui:35
+msgid ""
+"Automatically disable all physical displays when the XR effect is enabled."
msgstr ""
#: src/gtk/connected-device.ui:91
+msgid "Virtual displays"
+msgstr ""
+
+#: src/gtk/connected-device.ui:103
+msgid "Rearrange displays"
+msgstr ""
+
+#: src/gtk/connected-device.ui:115
+msgid "1080p"
+msgstr ""
+
+#: src/gtk/connected-device.ui:116
+msgid "1440p"
+msgstr ""
+
+#: src/gtk/connected-device.ui:140
msgid "Adjustments"
msgstr ""
-#: src/gtk/connected-device.ui:94
-msgid "Display distance"
+#: src/gtk/connected-device.ui:143
+msgid "Display distances"
msgstr ""
-#: src/gtk/connected-device.ui:95
-msgid ""
-"Closer appears larger, further appears smaller. Controls depth when in "
-"widescreen mode."
+#: src/gtk/connected-device.ui:144
+msgid "Set how close you want displays to appear."
msgstr ""
-#: src/gtk/connected-device.ui:123
-msgid "Display size"
-msgstr ""
-
-#: src/gtk/connected-device.ui:124
-msgid ""
-"Combine with display distance to achieve a comfortable level of depth and "
-"size."
-msgstr ""
-
-#: src/gtk/connected-device.ui:152
-msgid "Display toggle distances"
-msgstr ""
-
-#: src/gtk/connected-device.ui:153
-msgid ""
-"Use the buttons to capture the current display distance for use with the "
-"keyboard shortcut."
-msgstr ""
-
-#: src/gtk/connected-device.ui:178
+#: src/gtk/connected-device.ui:199
msgid "Follow threshold"
msgstr ""
-#: src/gtk/connected-device.ui:179
+#: src/gtk/connected-device.ui:200
msgid "How far away you can look before the display follows."
msgstr ""
-#: src/gtk/connected-device.ui:209 src/gtk/connected-device.ui:215
+#: src/gtk/connected-device.ui:223
+msgid "Display angling"
+msgstr ""
+
+#: src/gtk/connected-device.ui:224
+msgid ""
+"When there are multiple displays, choose how they should angle towards you."
+msgstr ""
+
+#: src/gtk/connected-device.ui:238
+msgid "Automatic"
+msgstr ""
+
+#: src/gtk/connected-device.ui:239
+msgid "Side-angled"
+msgstr ""
+
+#: src/gtk/connected-device.ui:240
+msgid "Top-angled"
+msgstr ""
+
+#: src/gtk/connected-device.ui:241
+msgid "Flat"
+msgstr ""
+
+#: src/gtk/connected-device.ui:251
+msgid "Display spacing"
+msgstr ""
+
+#: src/gtk/connected-device.ui:252
+msgid "Put empty space between displays, when there are multiple."
+msgstr ""
+
+#: src/gtk/connected-device.ui:282
+msgid "Viewport horizontal offset"
+msgstr ""
+
+#: src/gtk/connected-device.ui:283
+msgid ""
+"By default, the viewport will center on the primary display. Use this slider "
+"to move the viewport to the left or right."
+msgstr ""
+
+#: src/gtk/connected-device.ui:312
+msgid "Viewport vertical offset"
+msgstr ""
+
+#: src/gtk/connected-device.ui:313
+msgid ""
+"By default, the viewport will center on the primary display. Use this slider "
+"to move the viewport up or down."
+msgstr ""
+
+#: src/gtk/connected-device.ui:349 src/gtk/connected-device.ui:355
msgid "Keyboard Shortcuts"
msgstr ""
-#: src/gtk/connected-device.ui:218
+#: src/gtk/connected-device.ui:358
msgid "XR Effect on/off shortcut"
msgstr ""
-#: src/gtk/connected-device.ui:219
+#: src/gtk/connected-device.ui:359
msgid ""
"Quickly enable or disable the XR Effect. You may need to enable the effect "
"manually once in order to enable the shortcut."
msgstr ""
-#: src/gtk/connected-device.ui:238 src/gtk/connected-device.ui:267
-#: src/gtk/connected-device.ui:296 src/gtk/connected-device.ui:325
+#: src/gtk/connected-device.ui:378 src/gtk/connected-device.ui:407
+#: src/gtk/connected-device.ui:436 src/gtk/connected-device.ui:465
msgid "Change"
msgstr ""
-#: src/gtk/connected-device.ui:247
+#: src/gtk/connected-device.ui:387
msgid "Re-center display shortcut"
msgstr ""
-#: src/gtk/connected-device.ui:248
+#: src/gtk/connected-device.ui:388
msgid "Pin the virtual display to the current position."
msgstr ""
-#: src/gtk/connected-device.ui:276
-msgid "Display distance shortcut"
+#: src/gtk/connected-device.ui:416
+msgid "Toggle zoom on focus shortcut"
msgstr ""
-#: src/gtk/connected-device.ui:277
-msgid "Quickly toggle between two predefined distances."
+#: src/gtk/connected-device.ui:417
+msgid "Quickly toggle zoom on focus mode."
msgstr ""
-#: src/gtk/connected-device.ui:305
+#: src/gtk/connected-device.ui:445
msgid "Toggle follow mode shortcut"
msgstr ""
-#: src/gtk/connected-device.ui:306
+#: src/gtk/connected-device.ui:446
msgid "Quickly toggle follow mode."
msgstr ""
-#: src/gtk/connected-device.ui:341 src/gtk/connected-device.ui:347
+#: src/gtk/connected-device.ui:481 src/gtk/connected-device.ui:487
msgid "Advanced Settings"
msgstr ""
-#: src/gtk/connected-device.ui:350
+#: src/gtk/connected-device.ui:490
msgid "Find optimal display config"
msgstr ""
-#: src/gtk/connected-device.ui:351
+#: src/gtk/connected-device.ui:491
msgid ""
"Automatically modify the glasses display configuration for maximum "
"resolution and best scaling when plugged in."
msgstr ""
-#: src/gtk/connected-device.ui:361
+#: src/gtk/connected-device.ui:501
msgid "Use highest refresh rate"
msgstr ""
-#: src/gtk/connected-device.ui:362
+#: src/gtk/connected-device.ui:502
msgid "Refresh rate may affect performance, disable this to set it manually."
msgstr ""
-#: src/gtk/connected-device.ui:372
+#: src/gtk/connected-device.ui:512
msgid "Always primary display"
msgstr ""
-#: src/gtk/connected-device.ui:373
+#: src/gtk/connected-device.ui:513
msgid "Automatically set the glasses as the primary display when plugged in."
msgstr ""
-#: src/gtk/connected-device.ui:383
-msgid "Fast SBS mode switching"
-msgstr ""
-
-#: src/gtk/connected-device.ui:384
-msgid ""
-"Switches glasses to SBS mode immediately when plugged in, if widescreen mode "
-"is on. May cause instability."
-msgstr ""
-
-#: src/gtk/connected-device.ui:394
+#: src/gtk/connected-device.ui:523
msgid "Movement look-ahead"
msgstr ""
-#: src/gtk/connected-device.ui:395
+#: src/gtk/connected-device.ui:524
msgid ""
"Counteracts input lag by predicting head-tracking position ahead of render "
"time. Stick with default unless virtual display drags behind your head "
"movements, jumps ahead, or is very shaky."
msgstr ""
-#: src/gtk/connected-device.ui:413
+#: src/gtk/connected-device.ui:542
msgid "Default"
msgstr ""
-#: src/gtk/connected-device.ui:425
+#: src/gtk/connected-device.ui:554
msgid "Text Scaling"
msgstr ""
-#: src/gtk/connected-device.ui:426
+#: src/gtk/connected-device.ui:555
msgid "Scaling text below 1.0 will simulate a higher resolution display"
msgstr ""
+#: src/gtk/connected-device.ui:585
+msgid "Enable multi-tap detection"
+msgstr ""
+
+#: src/gtk/connected-device.ui:586
+msgid "Enables double-tap to recenter and triple-tap to recalibrate."
+msgstr ""
+
+#: src/gtk/display-distance-dialog.ui:9
+msgid "Show full range"
+msgstr ""
+
+#: src/gtk/display-distance-dialog.ui:18
+msgid "Done"
+msgstr ""
+
#: src/gtk/failed-verification.ui:13
msgid "Breezy Desktop GNOME invalid setup"
msgstr ""
@@ -376,14 +480,6 @@ msgid ""
"connected."
msgstr ""
-#: src/gtk/no-device.ui:34
-msgid "Start in widescreen mode"
-msgstr ""
-
-#: src/gtk/no-device.ui:35
-msgid "Widescreen mode is not supported for all glasses."
-msgstr ""
-
#: src/gtk/no-driver.ui:13
msgid "No driver running"
msgstr ""
diff --git a/ui/po/pt_BR.po b/ui/po/pt_BR.po
index 1ca89cc..c13a71b 100644
--- a/ui/po/pt_BR.po
+++ b/ui/po/pt_BR.po
@@ -7,18 +7,18 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-10-22 13:27-0700\n"
+"POT-Creation-Date: 2025-03-05 12:28-0800\n"
"PO-Revision-Date: 2024-08-19 09:39-0700\n"
"Last-Translator: \n"
-"Language-Team: Brazilian Portuguese \n"
+"Language-Team: Brazilian Portuguese \n"
"Language: pt_BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-#: src/connecteddevice.py:17
+#: src/connecteddevice.py:23
msgid ""
"Switches your glasses into side-by-side mode and doubles the width of the "
"display."
@@ -26,10 +26,56 @@ msgstr ""
"Altera o modo dos óculos para lado a lado (SBS) e dobra a largura da tela "
"(ultrawide)."
-#: src/connecteddevice.py:18
+#: src/connecteddevice.py:24
msgid "This feature is not currently supported for your device."
msgstr "Este recurso não é atualmente suportado para o seu dispositivo."
+#: src/connecteddevice.py:124
+#, fuzzy
+msgid "Set Focused Display Distance"
+msgstr "Distância da tela"
+
+#: src/connecteddevice.py:125
+msgid "Use a closer value so the display zooms in when you look at it."
+msgstr ""
+
+#: src/connecteddevice.py:132
+#, fuzzy
+msgid "Set All Displays Distance"
+msgstr "Distância da tela"
+
+#: src/connecteddevice.py:133
+msgid "Use a farther value so the displays are zoomed out when you look away."
+msgstr ""
+
+#: src/connecteddevice.py:231
+msgid ""
+"Unable to add virtual displays on this machine. xdg-desktop-portal is "
+"required."
+msgstr ""
+
+#: src/connecteddevice.py:265
+#, fuzzy
+msgid "Focused display"
+msgstr "Distância da tela"
+
+#: src/connecteddevice.py:271
+#, fuzzy
+msgid "All displays"
+msgstr "Tela curva"
+
+#: src/displaydistancedialogcontent.py:41
+msgid "closer"
+msgstr ""
+
+#: src/displaydistancedialogcontent.py:45
+msgid "fullscreen"
+msgstr ""
+
+#: src/displaydistancedialogcontent.py:48
+msgid "farther"
+msgstr ""
+
#: src/licensedialogcontent.py:63
msgid "Paid Tier Status"
msgstr "Status do Nível Pago"
@@ -38,7 +84,7 @@ msgstr "Status do Nível Pago"
msgid "Feature Availability"
msgstr "Disponibilidade de Recursos"
-#: src/licensefeaturerow.py:15 src/shortcutdialog.py:107
+#: src/licensefeaturerow.py:15 src/shortcutdialog.py:104
msgid "Disabled"
msgstr "Desabilitado"
@@ -167,125 +213,183 @@ msgid "Enables the Breezy Desktop XR effect."
msgstr "Habilita o efeito XR do Breezy Desktop."
#: src/gtk/connected-device.ui:55
-msgid "Widescreen mode"
-msgstr "Modo Ultrawide"
+msgid "Zoom on focus"
+msgstr ""
-#: src/gtk/connected-device.ui:66
+#: src/gtk/connected-device.ui:56
+msgid ""
+"Automatically move a display closer when you look at it.\n"
+"Set your preferred focused and unfocused distances in the Adjustments "
+"section.\n"
+" "
+msgstr ""
+
+#: src/gtk/connected-device.ui:69
msgid "Follow mode"
msgstr "Modo de acompanhamento"
-#: src/gtk/connected-device.ui:67
-msgid "Keep the virtual display near the center of your view."
+#: src/gtk/connected-device.ui:70
+#, fuzzy
+msgid "Keep the focused display near the center of your view."
msgstr "Mantenha a tela virtual próxima ao centro da sua visão."
-#: src/gtk/connected-device.ui:77
-msgid "Curved display"
-msgstr "Tela curva"
+#: src/gtk/connected-device.ui:80 src/gtk/no-device.ui:34
+msgid "Disable physical displays"
+msgstr ""
-#: src/gtk/connected-device.ui:78
-msgid "Switch between flat and curved displays."
-msgstr "Alterne entre tela plana e tela curva."
+#: src/gtk/connected-device.ui:81 src/gtk/no-device.ui:35
+msgid ""
+"Automatically disable all physical displays when the XR effect is enabled."
+msgstr ""
#: src/gtk/connected-device.ui:91
+#, fuzzy
+msgid "Virtual displays"
+msgstr "Tela curva"
+
+#: src/gtk/connected-device.ui:103
+#, fuzzy
+msgid "Rearrange displays"
+msgstr "Tela curva"
+
+#: src/gtk/connected-device.ui:115
+msgid "1080p"
+msgstr ""
+
+#: src/gtk/connected-device.ui:116
+msgid "1440p"
+msgstr ""
+
+#: src/gtk/connected-device.ui:140
msgid "Adjustments"
msgstr "Ajustes"
-#: src/gtk/connected-device.ui:94
-msgid "Display distance"
+#: src/gtk/connected-device.ui:143
+#, fuzzy
+msgid "Display distances"
msgstr "Distância da tela"
-#: src/gtk/connected-device.ui:95
-msgid ""
-"Closer appears larger, further appears smaller. Controls depth when in "
-"widescreen mode."
+#: src/gtk/connected-device.ui:144
+msgid "Set how close you want displays to appear."
msgstr ""
-"Mais perto parece maior, mais longe parece menor. Controla a profundidade no "
-"modo ultrawide."
-#: src/gtk/connected-device.ui:123
-msgid "Display size"
-msgstr "Tamanho da tela"
-
-#: src/gtk/connected-device.ui:124
-msgid ""
-"Combine with display distance to achieve a comfortable level of depth and "
-"size."
-msgstr ""
-"Combine com a distância da tela para alcançar um nível confortável de "
-"profundidade e tamanho."
-
-#: src/gtk/connected-device.ui:152
-msgid "Display toggle distances"
-msgstr "Alternância das distâncias de tela"
-
-#: src/gtk/connected-device.ui:153
-msgid ""
-"Use the buttons to capture the current display distance for use with the "
-"keyboard shortcut."
-msgstr ""
-"Use os botões para obter a distância atual da tela para depois usar com o "
-"atalho de teclado."
-
-#: src/gtk/connected-device.ui:178
+#: src/gtk/connected-device.ui:199
msgid "Follow threshold"
msgstr "Sensibilidade do modo de acompanhamento"
-#: src/gtk/connected-device.ui:179
+#: src/gtk/connected-device.ui:200
msgid "How far away you can look before the display follows."
msgstr "Quanto você pode mover a cabeça antes que a tela te acompanhe."
-#: src/gtk/connected-device.ui:209 src/gtk/connected-device.ui:215
+#: src/gtk/connected-device.ui:223
+#, fuzzy
+msgid "Display angling"
+msgstr "Tamanho da tela"
+
+#: src/gtk/connected-device.ui:224
+msgid ""
+"When there are multiple displays, choose how they should angle towards you."
+msgstr ""
+
+#: src/gtk/connected-device.ui:238
+msgid "Automatic"
+msgstr ""
+
+#: src/gtk/connected-device.ui:239
+msgid "Side-angled"
+msgstr ""
+
+#: src/gtk/connected-device.ui:240
+msgid "Top-angled"
+msgstr ""
+
+#: src/gtk/connected-device.ui:241
+msgid "Flat"
+msgstr ""
+
+#: src/gtk/connected-device.ui:251
+#, fuzzy
+msgid "Display spacing"
+msgstr "Tamanho da tela"
+
+#: src/gtk/connected-device.ui:252
+msgid "Put empty space between displays, when there are multiple."
+msgstr ""
+
+#: src/gtk/connected-device.ui:282
+msgid "Viewport horizontal offset"
+msgstr ""
+
+#: src/gtk/connected-device.ui:283
+msgid ""
+"By default, the viewport will center on the primary display. Use this slider "
+"to move the viewport to the left or right."
+msgstr ""
+
+#: src/gtk/connected-device.ui:312
+msgid "Viewport vertical offset"
+msgstr ""
+
+#: src/gtk/connected-device.ui:313
+msgid ""
+"By default, the viewport will center on the primary display. Use this slider "
+"to move the viewport up or down."
+msgstr ""
+
+#: src/gtk/connected-device.ui:349 src/gtk/connected-device.ui:355
msgid "Keyboard Shortcuts"
msgstr "Atalhos de teclado"
-#: src/gtk/connected-device.ui:218
+#: src/gtk/connected-device.ui:358
msgid "XR Effect on/off shortcut"
msgstr ""
-#: src/gtk/connected-device.ui:219
+#: src/gtk/connected-device.ui:359
msgid ""
"Quickly enable or disable the XR Effect. You may need to enable the effect "
"manually once in order to enable the shortcut."
msgstr ""
-#: src/gtk/connected-device.ui:238 src/gtk/connected-device.ui:267
-#: src/gtk/connected-device.ui:296 src/gtk/connected-device.ui:325
+#: src/gtk/connected-device.ui:378 src/gtk/connected-device.ui:407
+#: src/gtk/connected-device.ui:436 src/gtk/connected-device.ui:465
msgid "Change"
msgstr "Alterar"
-#: src/gtk/connected-device.ui:247
+#: src/gtk/connected-device.ui:387
msgid "Re-center display shortcut"
msgstr "Atalho para recentralizar a tela"
-#: src/gtk/connected-device.ui:248
+#: src/gtk/connected-device.ui:388
msgid "Pin the virtual display to the current position."
msgstr "Traga a tela virtual para onde você está olhando."
-#: src/gtk/connected-device.ui:276
-msgid "Display distance shortcut"
-msgstr "Atalho de distância da tela"
+#: src/gtk/connected-device.ui:416
+#, fuzzy
+msgid "Toggle zoom on focus shortcut"
+msgstr "Atalho para alternar o modo de acompanhamento"
-#: src/gtk/connected-device.ui:277
-msgid "Quickly toggle between two predefined distances."
-msgstr "Alterne rapidamente entre as duas distâncias predefinidas."
+#: src/gtk/connected-device.ui:417
+#, fuzzy
+msgid "Quickly toggle zoom on focus mode."
+msgstr "Alterne rapidamente o modo de acompanhamento."
-#: src/gtk/connected-device.ui:305
+#: src/gtk/connected-device.ui:445
msgid "Toggle follow mode shortcut"
msgstr "Atalho para alternar o modo de acompanhamento"
-#: src/gtk/connected-device.ui:306
+#: src/gtk/connected-device.ui:446
msgid "Quickly toggle follow mode."
msgstr "Alterne rapidamente o modo de acompanhamento."
-#: src/gtk/connected-device.ui:341 src/gtk/connected-device.ui:347
+#: src/gtk/connected-device.ui:481 src/gtk/connected-device.ui:487
msgid "Advanced Settings"
msgstr "Configurações Avançadas"
-#: src/gtk/connected-device.ui:350
+#: src/gtk/connected-device.ui:490
msgid "Find optimal display config"
msgstr "Encontre a configuração de tela ideal"
-#: src/gtk/connected-device.ui:351
+#: src/gtk/connected-device.ui:491
msgid ""
"Automatically modify the glasses display configuration for maximum "
"resolution and best scaling when plugged in."
@@ -293,42 +397,30 @@ msgstr ""
"Modifique automaticamente a configuração de exibição dos óculos para máxima "
"resolução e melhor dimensionamento quando conectado."
-#: src/gtk/connected-device.ui:361
+#: src/gtk/connected-device.ui:501
msgid "Use highest refresh rate"
msgstr "Use a taxa de atualização mais alta"
-#: src/gtk/connected-device.ui:362
+#: src/gtk/connected-device.ui:502
msgid "Refresh rate may affect performance, disable this to set it manually."
msgstr ""
"A taxa de atualização pode afetar o desempenho, desative-a para defini-la "
"manualmente."
-#: src/gtk/connected-device.ui:372
+#: src/gtk/connected-device.ui:512
msgid "Always primary display"
msgstr "Sempre tela principal"
-#: src/gtk/connected-device.ui:373
+#: src/gtk/connected-device.ui:513
msgid "Automatically set the glasses as the primary display when plugged in."
msgstr ""
"Defina automaticamente os óculos como a tela primária quando conectados."
-#: src/gtk/connected-device.ui:383
-msgid "Fast SBS mode switching"
-msgstr "Alternância rápida do modo SBS"
-
-#: src/gtk/connected-device.ui:384
-msgid ""
-"Switches glasses to SBS mode immediately when plugged in, if widescreen mode "
-"is on. May cause instability."
-msgstr ""
-"Altera os óculos para o modo SBS imediatamente quando conectados, se o modo "
-"ultrawide estiver ativado. Pode causar instabilidade."
-
-#: src/gtk/connected-device.ui:394
+#: src/gtk/connected-device.ui:523
msgid "Movement look-ahead"
msgstr "Antecipação de movimento"
-#: src/gtk/connected-device.ui:395
+#: src/gtk/connected-device.ui:524
msgid ""
"Counteracts input lag by predicting head-tracking position ahead of render "
"time. Stick with default unless virtual display drags behind your head "
@@ -339,19 +431,35 @@ msgstr ""
"virtual tenha atrasos, avance ou seja muito instável em relação aos "
"movimentos da cabeça "
-#: src/gtk/connected-device.ui:413
+#: src/gtk/connected-device.ui:542
msgid "Default"
msgstr "Padrão"
-#: src/gtk/connected-device.ui:425
+#: src/gtk/connected-device.ui:554
msgid "Text Scaling"
msgstr "Redimensionamento de Texto"
-#: src/gtk/connected-device.ui:426
+#: src/gtk/connected-device.ui:555
msgid "Scaling text below 1.0 will simulate a higher resolution display"
msgstr ""
"Redimensionar o texto abaixo de 1.0 simulará uma tela de resolução mais alta"
+#: src/gtk/connected-device.ui:585
+msgid "Enable multi-tap detection"
+msgstr ""
+
+#: src/gtk/connected-device.ui:586
+msgid "Enables double-tap to recenter and triple-tap to recalibrate."
+msgstr ""
+
+#: src/gtk/display-distance-dialog.ui:9
+msgid "Show full range"
+msgstr ""
+
+#: src/gtk/display-distance-dialog.ui:18
+msgid "Done"
+msgstr ""
+
#: src/gtk/failed-verification.ui:13
msgid "Breezy Desktop GNOME invalid setup"
msgstr "Configuração inválida do Breezy Desktop GNOME"
@@ -401,15 +509,6 @@ msgid ""
"connected."
msgstr ""
-#: src/gtk/no-device.ui:34
-#, fuzzy
-msgid "Start in widescreen mode"
-msgstr "Modo Ultrawide"
-
-#: src/gtk/no-device.ui:35
-msgid "Widescreen mode is not supported for all glasses."
-msgstr ""
-
#: src/gtk/no-driver.ui:13
msgid "No driver running"
msgstr "Nenhum driver em execução"
@@ -516,3 +615,57 @@ msgstr "Forçar redefinição"
#: src/gtk/window.ui:99
msgid "About BreezyDesktop"
msgstr "Sobre o BreezyDesktop"
+
+#~ msgid "Fast SBS mode switching"
+#~ msgstr "Alternância rápida do modo SBS"
+
+#~ msgid ""
+#~ "Switches glasses to SBS mode immediately when plugged in, if widescreen "
+#~ "mode is on. May cause instability."
+#~ msgstr ""
+#~ "Altera os óculos para o modo SBS imediatamente quando conectados, se o "
+#~ "modo ultrawide estiver ativado. Pode causar instabilidade."
+
+#, fuzzy
+#~ msgid "Set Unfocused Displays Distance"
+#~ msgstr "Distância da tela"
+
+#~ msgid "Widescreen mode"
+#~ msgstr "Modo Ultrawide"
+
+#~ msgid "Switch between flat and curved displays."
+#~ msgstr "Alterne entre tela plana e tela curva."
+
+#~ msgid ""
+#~ "Closer appears larger, further appears smaller. Controls depth when in "
+#~ "widescreen mode."
+#~ msgstr ""
+#~ "Mais perto parece maior, mais longe parece menor. Controla a profundidade "
+#~ "no modo ultrawide."
+
+#~ msgid ""
+#~ "Combine with display distance to achieve a comfortable level of depth and "
+#~ "size."
+#~ msgstr ""
+#~ "Combine com a distância da tela para alcançar um nível confortável de "
+#~ "profundidade e tamanho."
+
+#~ msgid "Display toggle distances"
+#~ msgstr "Alternância das distâncias de tela"
+
+#~ msgid ""
+#~ "Use the buttons to capture the current display distance for use with the "
+#~ "keyboard shortcut."
+#~ msgstr ""
+#~ "Use os botões para obter a distância atual da tela para depois usar com o "
+#~ "atalho de teclado."
+
+#~ msgid "Display distance shortcut"
+#~ msgstr "Atalho de distância da tela"
+
+#~ msgid "Quickly toggle between two predefined distances."
+#~ msgstr "Alterne rapidamente entre as duas distâncias predefinidas."
+
+#, fuzzy
+#~ msgid "Start in widescreen mode"
+#~ msgstr "Modo Ultrawide"
diff --git a/ui/po/ru.po b/ui/po/ru.po
index da7815e..2df8733 100644
--- a/ui/po/ru.po
+++ b/ui/po/ru.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-10-22 13:27-0700\n"
+"POT-Creation-Date: 2025-03-05 12:28-0800\n"
"PO-Revision-Date: 2024-08-17 09:39-0700\n"
"Last-Translator: \n"
"Language-Team: Russian \n"
@@ -18,17 +18,63 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-#: src/connecteddevice.py:17
+#: src/connecteddevice.py:23
msgid ""
"Switches your glasses into side-by-side mode and doubles the width of the "
"display."
msgstr ""
"Переключает очки в режим «сторона к стороне» и удваивает ширину дисплея."
-#: src/connecteddevice.py:18
+#: src/connecteddevice.py:24
msgid "This feature is not currently supported for your device."
msgstr "Эта функция в настоящее время не поддерживается для вашего устройства."
+#: src/connecteddevice.py:124
+#, fuzzy
+msgid "Set Focused Display Distance"
+msgstr "Расстояние дисплея"
+
+#: src/connecteddevice.py:125
+msgid "Use a closer value so the display zooms in when you look at it."
+msgstr ""
+
+#: src/connecteddevice.py:132
+#, fuzzy
+msgid "Set All Displays Distance"
+msgstr "Расстояние дисплея"
+
+#: src/connecteddevice.py:133
+msgid "Use a farther value so the displays are zoomed out when you look away."
+msgstr ""
+
+#: src/connecteddevice.py:231
+msgid ""
+"Unable to add virtual displays on this machine. xdg-desktop-portal is "
+"required."
+msgstr ""
+
+#: src/connecteddevice.py:265
+#, fuzzy
+msgid "Focused display"
+msgstr "Расстояние дисплея"
+
+#: src/connecteddevice.py:271
+#, fuzzy
+msgid "All displays"
+msgstr "Изогнутый дисплей"
+
+#: src/displaydistancedialogcontent.py:41
+msgid "closer"
+msgstr ""
+
+#: src/displaydistancedialogcontent.py:45
+msgid "fullscreen"
+msgstr ""
+
+#: src/displaydistancedialogcontent.py:48
+msgid "farther"
+msgstr ""
+
#: src/licensedialogcontent.py:63
msgid "Paid Tier Status"
msgstr "Статус платного уровня"
@@ -37,7 +83,7 @@ msgstr "Статус платного уровня"
msgid "Feature Availability"
msgstr "Статус функций"
-#: src/licensefeaturerow.py:15 src/shortcutdialog.py:107
+#: src/licensefeaturerow.py:15 src/shortcutdialog.py:104
msgid "Disabled"
msgstr "Отключено"
@@ -166,126 +212,184 @@ msgid "Enables the Breezy Desktop XR effect."
msgstr "Включает эффект Breezy Desktop XR."
#: src/gtk/connected-device.ui:55
-msgid "Widescreen mode"
-msgstr "Режим широкого экрана"
+msgid "Zoom on focus"
+msgstr ""
-#: src/gtk/connected-device.ui:66
+#: src/gtk/connected-device.ui:56
+msgid ""
+"Automatically move a display closer when you look at it.\n"
+"Set your preferred focused and unfocused distances in the Adjustments "
+"section.\n"
+" "
+msgstr ""
+
+#: src/gtk/connected-device.ui:69
msgid "Follow mode"
msgstr "Режим следования"
-#: src/gtk/connected-device.ui:67
-msgid "Keep the virtual display near the center of your view."
+#: src/gtk/connected-device.ui:70
+#, fuzzy
+msgid "Keep the focused display near the center of your view."
msgstr "Поддерживает виртуальный дисплей вблизи центра вашего зрения."
-#: src/gtk/connected-device.ui:77
-msgid "Curved display"
-msgstr "Изогнутый дисплей"
+#: src/gtk/connected-device.ui:80 src/gtk/no-device.ui:34
+msgid "Disable physical displays"
+msgstr ""
-#: src/gtk/connected-device.ui:78
-msgid "Switch between flat and curved displays."
-msgstr "Переключается между плоскими и изогнутыми дисплеями."
+#: src/gtk/connected-device.ui:81 src/gtk/no-device.ui:35
+msgid ""
+"Automatically disable all physical displays when the XR effect is enabled."
+msgstr ""
#: src/gtk/connected-device.ui:91
+#, fuzzy
+msgid "Virtual displays"
+msgstr "Изогнутый дисплей"
+
+#: src/gtk/connected-device.ui:103
+#, fuzzy
+msgid "Rearrange displays"
+msgstr "Изогнутый дисплей"
+
+#: src/gtk/connected-device.ui:115
+msgid "1080p"
+msgstr ""
+
+#: src/gtk/connected-device.ui:116
+msgid "1440p"
+msgstr ""
+
+#: src/gtk/connected-device.ui:140
msgid "Adjustments"
msgstr "Настройки"
-#: src/gtk/connected-device.ui:94
-msgid "Display distance"
+#: src/gtk/connected-device.ui:143
+#, fuzzy
+msgid "Display distances"
msgstr "Расстояние дисплея"
-#: src/gtk/connected-device.ui:95
-msgid ""
-"Closer appears larger, further appears smaller. Controls depth when in "
-"widescreen mode."
+#: src/gtk/connected-device.ui:144
+msgid "Set how close you want displays to appear."
msgstr ""
-"Чем ближе, тем больше. Чем дальше, тем меньше. Управляет глубиной при "
-"использовании режима широкого экрана."
-#: src/gtk/connected-device.ui:123
-msgid "Display size"
-msgstr "Размер дисплея"
-
-#: src/gtk/connected-device.ui:124
-msgid ""
-"Combine with display distance to achieve a comfortable level of depth and "
-"size."
-msgstr ""
-"Комбинируйте с расстоянием дисплея, чтобы достичь комфортного уровня глубины "
-"и размера."
-
-#: src/gtk/connected-device.ui:152
-msgid "Display toggle distances"
-msgstr "Переключения расстояние дисплея"
-
-#: src/gtk/connected-device.ui:153
-msgid ""
-"Use the buttons to capture the current display distance for use with the "
-"keyboard shortcut."
-msgstr ""
-"Используйте кнопки, чтобы зафиксировать текущее расстояние дисплея для "
-"использования с сочетанием клавиш."
-
-#: src/gtk/connected-device.ui:178
+#: src/gtk/connected-device.ui:199
msgid "Follow threshold"
msgstr "Порог следования"
-#: src/gtk/connected-device.ui:179
+#: src/gtk/connected-device.ui:200
msgid "How far away you can look before the display follows."
msgstr ""
"Как далеко вы можете отвернуть взгляд, прежде чем дисплей последует за вами."
-#: src/gtk/connected-device.ui:209 src/gtk/connected-device.ui:215
+#: src/gtk/connected-device.ui:223
+#, fuzzy
+msgid "Display angling"
+msgstr "Размер дисплея"
+
+#: src/gtk/connected-device.ui:224
+msgid ""
+"When there are multiple displays, choose how they should angle towards you."
+msgstr ""
+
+#: src/gtk/connected-device.ui:238
+msgid "Automatic"
+msgstr ""
+
+#: src/gtk/connected-device.ui:239
+msgid "Side-angled"
+msgstr ""
+
+#: src/gtk/connected-device.ui:240
+msgid "Top-angled"
+msgstr ""
+
+#: src/gtk/connected-device.ui:241
+msgid "Flat"
+msgstr ""
+
+#: src/gtk/connected-device.ui:251
+#, fuzzy
+msgid "Display spacing"
+msgstr "Размер дисплея"
+
+#: src/gtk/connected-device.ui:252
+msgid "Put empty space between displays, when there are multiple."
+msgstr ""
+
+#: src/gtk/connected-device.ui:282
+msgid "Viewport horizontal offset"
+msgstr ""
+
+#: src/gtk/connected-device.ui:283
+msgid ""
+"By default, the viewport will center on the primary display. Use this slider "
+"to move the viewport to the left or right."
+msgstr ""
+
+#: src/gtk/connected-device.ui:312
+msgid "Viewport vertical offset"
+msgstr ""
+
+#: src/gtk/connected-device.ui:313
+msgid ""
+"By default, the viewport will center on the primary display. Use this slider "
+"to move the viewport up or down."
+msgstr ""
+
+#: src/gtk/connected-device.ui:349 src/gtk/connected-device.ui:355
msgid "Keyboard Shortcuts"
msgstr "Сочетания клавиш"
-#: src/gtk/connected-device.ui:218
+#: src/gtk/connected-device.ui:358
msgid "XR Effect on/off shortcut"
msgstr ""
-#: src/gtk/connected-device.ui:219
+#: src/gtk/connected-device.ui:359
msgid ""
"Quickly enable or disable the XR Effect. You may need to enable the effect "
"manually once in order to enable the shortcut."
msgstr ""
-#: src/gtk/connected-device.ui:238 src/gtk/connected-device.ui:267
-#: src/gtk/connected-device.ui:296 src/gtk/connected-device.ui:325
+#: src/gtk/connected-device.ui:378 src/gtk/connected-device.ui:407
+#: src/gtk/connected-device.ui:436 src/gtk/connected-device.ui:465
msgid "Change"
msgstr "Изменить"
-#: src/gtk/connected-device.ui:247
+#: src/gtk/connected-device.ui:387
msgid "Re-center display shortcut"
msgstr "Сочетание клавиш для перецентровки дисплея"
-#: src/gtk/connected-device.ui:248
+#: src/gtk/connected-device.ui:388
msgid "Pin the virtual display to the current position."
msgstr "Фиксировать виртуальный дисплей в текущем положении."
-#: src/gtk/connected-device.ui:276
-msgid "Display distance shortcut"
-msgstr "Сочетание клавиш для расстояния дисплея"
+#: src/gtk/connected-device.ui:416
+#, fuzzy
+msgid "Toggle zoom on focus shortcut"
+msgstr "Сочетание клавиш для переключения режима следования"
-#: src/gtk/connected-device.ui:277
-msgid "Quickly toggle between two predefined distances."
-msgstr "Быстро переключаться между двумя предопределенными расстояниями."
+#: src/gtk/connected-device.ui:417
+#, fuzzy
+msgid "Quickly toggle zoom on focus mode."
+msgstr "Быстро переключать режим следования."
-#: src/gtk/connected-device.ui:305
+#: src/gtk/connected-device.ui:445
msgid "Toggle follow mode shortcut"
msgstr "Сочетание клавиш для переключения режима следования"
-#: src/gtk/connected-device.ui:306
+#: src/gtk/connected-device.ui:446
msgid "Quickly toggle follow mode."
msgstr "Быстро переключать режим следования."
-#: src/gtk/connected-device.ui:341 src/gtk/connected-device.ui:347
+#: src/gtk/connected-device.ui:481 src/gtk/connected-device.ui:487
msgid "Advanced Settings"
msgstr "Дополнительные настройки"
-#: src/gtk/connected-device.ui:350
+#: src/gtk/connected-device.ui:490
msgid "Find optimal display config"
msgstr "Найти оптимальную конфигурацию дисплея"
-#: src/gtk/connected-device.ui:351
+#: src/gtk/connected-device.ui:491
msgid ""
"Automatically modify the glasses display configuration for maximum "
"resolution and best scaling when plugged in."
@@ -293,43 +397,31 @@ msgstr ""
"Автоматически изменять конфигурацию дисплея очков для максимального "
"разрешения и лучшей масштабирования при подключении."
-#: src/gtk/connected-device.ui:361
+#: src/gtk/connected-device.ui:501
msgid "Use highest refresh rate"
msgstr "Использовать высшую частоту обновления"
-#: src/gtk/connected-device.ui:362
+#: src/gtk/connected-device.ui:502
msgid "Refresh rate may affect performance, disable this to set it manually."
msgstr ""
"Частота обновления может повлиять на производительность, отключите это, "
"чтобы установить ее вручную."
-#: src/gtk/connected-device.ui:372
+#: src/gtk/connected-device.ui:512
msgid "Always primary display"
msgstr "Всегда основной дисплей"
-#: src/gtk/connected-device.ui:373
+#: src/gtk/connected-device.ui:513
msgid "Automatically set the glasses as the primary display when plugged in."
msgstr ""
"Автоматически устанавливать очки в качестве основного дисплея при "
"подключении."
-#: src/gtk/connected-device.ui:383
-msgid "Fast SBS mode switching"
-msgstr "Быстрое переключение режима SBS"
-
-#: src/gtk/connected-device.ui:384
-msgid ""
-"Switches glasses to SBS mode immediately when plugged in, if widescreen mode "
-"is on. May cause instability."
-msgstr ""
-"Переключает очки в режим SBS сразу при подключении, если режим широкого "
-"экрана включен. Может вызвать нестабильность."
-
-#: src/gtk/connected-device.ui:394
+#: src/gtk/connected-device.ui:523
msgid "Movement look-ahead"
msgstr "Прогнозирование движения"
-#: src/gtk/connected-device.ui:395
+#: src/gtk/connected-device.ui:524
msgid ""
"Counteracts input lag by predicting head-tracking position ahead of render "
"time. Stick with default unless virtual display drags behind your head "
@@ -340,18 +432,34 @@ msgstr ""
"виртуальный дисплей не отстает от движений вашей головы, не опережает или не "
"очень трясётся."
-#: src/gtk/connected-device.ui:413
+#: src/gtk/connected-device.ui:542
msgid "Default"
msgstr "По умолчанию"
-#: src/gtk/connected-device.ui:425
+#: src/gtk/connected-device.ui:554
msgid "Text Scaling"
msgstr ""
-#: src/gtk/connected-device.ui:426
+#: src/gtk/connected-device.ui:555
msgid "Scaling text below 1.0 will simulate a higher resolution display"
msgstr ""
+#: src/gtk/connected-device.ui:585
+msgid "Enable multi-tap detection"
+msgstr ""
+
+#: src/gtk/connected-device.ui:586
+msgid "Enables double-tap to recenter and triple-tap to recalibrate."
+msgstr ""
+
+#: src/gtk/display-distance-dialog.ui:9
+msgid "Show full range"
+msgstr ""
+
+#: src/gtk/display-distance-dialog.ui:18
+msgid "Done"
+msgstr ""
+
#: src/gtk/failed-verification.ui:13
msgid "Breezy Desktop GNOME invalid setup"
msgstr "Недействительная настройка Breezy Desktop GNOME"
@@ -400,15 +508,6 @@ msgid ""
"connected."
msgstr ""
-#: src/gtk/no-device.ui:34
-#, fuzzy
-msgid "Start in widescreen mode"
-msgstr "Режим широкого экрана"
-
-#: src/gtk/no-device.ui:35
-msgid "Widescreen mode is not supported for all glasses."
-msgstr ""
-
#: src/gtk/no-driver.ui:13
msgid "No driver running"
msgstr "Драйвер не запущен"
@@ -517,3 +616,57 @@ msgstr "Сброс"
#: src/gtk/window.ui:99
msgid "About BreezyDesktop"
msgstr "О BreezyDesktop"
+
+#~ msgid "Fast SBS mode switching"
+#~ msgstr "Быстрое переключение режима SBS"
+
+#~ msgid ""
+#~ "Switches glasses to SBS mode immediately when plugged in, if widescreen "
+#~ "mode is on. May cause instability."
+#~ msgstr ""
+#~ "Переключает очки в режим SBS сразу при подключении, если режим широкого "
+#~ "экрана включен. Может вызвать нестабильность."
+
+#, fuzzy
+#~ msgid "Set Unfocused Displays Distance"
+#~ msgstr "Расстояние дисплея"
+
+#~ msgid "Widescreen mode"
+#~ msgstr "Режим широкого экрана"
+
+#~ msgid "Switch between flat and curved displays."
+#~ msgstr "Переключается между плоскими и изогнутыми дисплеями."
+
+#~ msgid ""
+#~ "Closer appears larger, further appears smaller. Controls depth when in "
+#~ "widescreen mode."
+#~ msgstr ""
+#~ "Чем ближе, тем больше. Чем дальше, тем меньше. Управляет глубиной при "
+#~ "использовании режима широкого экрана."
+
+#~ msgid ""
+#~ "Combine with display distance to achieve a comfortable level of depth and "
+#~ "size."
+#~ msgstr ""
+#~ "Комбинируйте с расстоянием дисплея, чтобы достичь комфортного уровня "
+#~ "глубины и размера."
+
+#~ msgid "Display toggle distances"
+#~ msgstr "Переключения расстояние дисплея"
+
+#~ msgid ""
+#~ "Use the buttons to capture the current display distance for use with the "
+#~ "keyboard shortcut."
+#~ msgstr ""
+#~ "Используйте кнопки, чтобы зафиксировать текущее расстояние дисплея для "
+#~ "использования с сочетанием клавиш."
+
+#~ msgid "Display distance shortcut"
+#~ msgstr "Сочетание клавиш для расстояния дисплея"
+
+#~ msgid "Quickly toggle between two predefined distances."
+#~ msgstr "Быстро переключаться между двумя предопределенными расстояниями."
+
+#, fuzzy
+#~ msgid "Start in widescreen mode"
+#~ msgstr "Режим широкого экрана"
diff --git a/ui/po/sv.po b/ui/po/sv.po
index dd5fc39..07fc116 100644
--- a/ui/po/sv.po
+++ b/ui/po/sv.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-10-22 13:27-0700\n"
+"POT-Creation-Date: 2025-03-05 12:28-0800\n"
"PO-Revision-Date: 2024-08-16 10:31-0700\n"
"Last-Translator: \n"
"Language-Team: Swedish \n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: src/connecteddevice.py:17
+#: src/connecteddevice.py:23
msgid ""
"Switches your glasses into side-by-side mode and doubles the width of the "
"display."
@@ -25,10 +25,56 @@ msgstr ""
"Växlar dina glasögon till side-by-side-läget och dubblerar bredden på "
"visningen."
-#: src/connecteddevice.py:18
+#: src/connecteddevice.py:24
msgid "This feature is not currently supported for your device."
msgstr "Din enhet stöder inte den här funktionen för tillfället."
+#: src/connecteddevice.py:124
+#, fuzzy
+msgid "Set Focused Display Distance"
+msgstr "Avstånd till skärmen"
+
+#: src/connecteddevice.py:125
+msgid "Use a closer value so the display zooms in when you look at it."
+msgstr ""
+
+#: src/connecteddevice.py:132
+#, fuzzy
+msgid "Set All Displays Distance"
+msgstr "Avstånd till skärmen"
+
+#: src/connecteddevice.py:133
+msgid "Use a farther value so the displays are zoomed out when you look away."
+msgstr ""
+
+#: src/connecteddevice.py:231
+msgid ""
+"Unable to add virtual displays on this machine. xdg-desktop-portal is "
+"required."
+msgstr ""
+
+#: src/connecteddevice.py:265
+#, fuzzy
+msgid "Focused display"
+msgstr "Avstånd till skärmen"
+
+#: src/connecteddevice.py:271
+#, fuzzy
+msgid "All displays"
+msgstr "Böjd skärm"
+
+#: src/displaydistancedialogcontent.py:41
+msgid "closer"
+msgstr ""
+
+#: src/displaydistancedialogcontent.py:45
+msgid "fullscreen"
+msgstr ""
+
+#: src/displaydistancedialogcontent.py:48
+msgid "farther"
+msgstr ""
+
#: src/licensedialogcontent.py:63
msgid "Paid Tier Status"
msgstr "Betalningsstatus"
@@ -37,7 +83,7 @@ msgstr "Betalningsstatus"
msgid "Feature Availability"
msgstr "Funktions tillgänglighet"
-#: src/licensefeaturerow.py:15 src/shortcutdialog.py:107
+#: src/licensefeaturerow.py:15 src/shortcutdialog.py:104
msgid "Disabled"
msgstr "Inaktiverad"
@@ -166,82 +212,138 @@ msgid "Enables the Breezy Desktop XR effect."
msgstr "Aktiverar Breezy Desktop XR-effekten."
#: src/gtk/connected-device.ui:55
-msgid "Widescreen mode"
-msgstr "Bredbildsläge"
+msgid "Zoom on focus"
+msgstr ""
-#: src/gtk/connected-device.ui:66
+#: src/gtk/connected-device.ui:56
+msgid ""
+"Automatically move a display closer when you look at it.\n"
+"Set your preferred focused and unfocused distances in the Adjustments "
+"section.\n"
+" "
+msgstr ""
+
+#: src/gtk/connected-device.ui:69
msgid "Follow mode"
msgstr "Följningsläge"
-#: src/gtk/connected-device.ui:67
-msgid "Keep the virtual display near the center of your view."
+#: src/gtk/connected-device.ui:70
+#, fuzzy
+msgid "Keep the focused display near the center of your view."
msgstr "Håll den virtuella skärmen nära mitten av din syn."
-#: src/gtk/connected-device.ui:77
-msgid "Curved display"
-msgstr "Böjd skärm"
+#: src/gtk/connected-device.ui:80 src/gtk/no-device.ui:34
+msgid "Disable physical displays"
+msgstr ""
-#: src/gtk/connected-device.ui:78
-msgid "Switch between flat and curved displays."
-msgstr "Växla mellan platt eller böjd skärm."
+#: src/gtk/connected-device.ui:81 src/gtk/no-device.ui:35
+msgid ""
+"Automatically disable all physical displays when the XR effect is enabled."
+msgstr ""
#: src/gtk/connected-device.ui:91
+#, fuzzy
+msgid "Virtual displays"
+msgstr "Böjd skärm"
+
+#: src/gtk/connected-device.ui:103
+#, fuzzy
+msgid "Rearrange displays"
+msgstr "Böjd skärm"
+
+#: src/gtk/connected-device.ui:115
+msgid "1080p"
+msgstr ""
+
+#: src/gtk/connected-device.ui:116
+msgid "1440p"
+msgstr ""
+
+#: src/gtk/connected-device.ui:140
msgid "Adjustments"
msgstr "Justeringar"
-#: src/gtk/connected-device.ui:94
-msgid "Display distance"
+#: src/gtk/connected-device.ui:143
+#, fuzzy
+msgid "Display distances"
msgstr "Avstånd till skärmen"
-#: src/gtk/connected-device.ui:95
-msgid ""
-"Closer appears larger, further appears smaller. Controls depth when in "
-"widescreen mode."
+#: src/gtk/connected-device.ui:144
+msgid "Set how close you want displays to appear."
msgstr ""
-"Närmare verkar större, längre verkar mindre. Kontrollerar djupet när du är i "
-"bredbildsläge."
-#: src/gtk/connected-device.ui:123
-msgid "Display size"
-msgstr "Skärmens storlek"
-
-#: src/gtk/connected-device.ui:124
-msgid ""
-"Combine with display distance to achieve a comfortable level of depth and "
-"size."
-msgstr ""
-"Kombinera med skärmens avstånd för att uppnå en bekväm nivå av djup och "
-"storlek."
-
-#: src/gtk/connected-device.ui:152
-msgid "Display toggle distances"
-msgstr "Växla skärm-avstånd"
-
-#: src/gtk/connected-device.ui:153
-msgid ""
-"Use the buttons to capture the current display distance for use with the "
-"keyboard shortcut."
-msgstr ""
-"Använd knapparna för att fanga nuvarande skärmavståndet för användning med "
-"tangentbordsgenvägar."
-
-#: src/gtk/connected-device.ui:178
+#: src/gtk/connected-device.ui:199
msgid "Follow threshold"
msgstr "Automatisk följtröskel"
-#: src/gtk/connected-device.ui:179
+#: src/gtk/connected-device.ui:200
msgid "How far away you can look before the display follows."
msgstr "Huvudrörelsetröskel för automatisk efterföljning."
-#: src/gtk/connected-device.ui:209 src/gtk/connected-device.ui:215
+#: src/gtk/connected-device.ui:223
+#, fuzzy
+msgid "Display angling"
+msgstr "Skärmens storlek"
+
+#: src/gtk/connected-device.ui:224
+msgid ""
+"When there are multiple displays, choose how they should angle towards you."
+msgstr ""
+
+#: src/gtk/connected-device.ui:238
+msgid "Automatic"
+msgstr ""
+
+#: src/gtk/connected-device.ui:239
+msgid "Side-angled"
+msgstr ""
+
+#: src/gtk/connected-device.ui:240
+msgid "Top-angled"
+msgstr ""
+
+#: src/gtk/connected-device.ui:241
+msgid "Flat"
+msgstr ""
+
+#: src/gtk/connected-device.ui:251
+#, fuzzy
+msgid "Display spacing"
+msgstr "Skärmens storlek"
+
+#: src/gtk/connected-device.ui:252
+msgid "Put empty space between displays, when there are multiple."
+msgstr ""
+
+#: src/gtk/connected-device.ui:282
+msgid "Viewport horizontal offset"
+msgstr ""
+
+#: src/gtk/connected-device.ui:283
+msgid ""
+"By default, the viewport will center on the primary display. Use this slider "
+"to move the viewport to the left or right."
+msgstr ""
+
+#: src/gtk/connected-device.ui:312
+msgid "Viewport vertical offset"
+msgstr ""
+
+#: src/gtk/connected-device.ui:313
+msgid ""
+"By default, the viewport will center on the primary display. Use this slider "
+"to move the viewport up or down."
+msgstr ""
+
+#: src/gtk/connected-device.ui:349 src/gtk/connected-device.ui:355
msgid "Keyboard Shortcuts"
msgstr "Tangentbordsgenvägar"
-#: src/gtk/connected-device.ui:218
+#: src/gtk/connected-device.ui:358
msgid "XR Effect on/off shortcut"
msgstr "XR-Effekt genväg på/av"
-#: src/gtk/connected-device.ui:219
+#: src/gtk/connected-device.ui:359
msgid ""
"Quickly enable or disable the XR Effect. You may need to enable the effect "
"manually once in order to enable the shortcut."
@@ -249,44 +351,46 @@ msgstr ""
"Skifta snabbt mellan att slå av eller på XR-Effekt. Du kan behöva slå på den "
"manuellt en gång för att genvägen ska fungera."
-#: src/gtk/connected-device.ui:238 src/gtk/connected-device.ui:267
-#: src/gtk/connected-device.ui:296 src/gtk/connected-device.ui:325
+#: src/gtk/connected-device.ui:378 src/gtk/connected-device.ui:407
+#: src/gtk/connected-device.ui:436 src/gtk/connected-device.ui:465
msgid "Change"
msgstr "Ändra"
-#: src/gtk/connected-device.ui:247
+#: src/gtk/connected-device.ui:387
msgid "Re-center display shortcut"
msgstr "Om-centrering tangentbordsgenväg"
-#: src/gtk/connected-device.ui:248
+#: src/gtk/connected-device.ui:388
msgid "Pin the virtual display to the current position."
msgstr "Fäst den virtuella skärmen i den nuvarande positionen."
-#: src/gtk/connected-device.ui:276
-msgid "Display distance shortcut"
-msgstr "Skärm avstånd genväg"
+#: src/gtk/connected-device.ui:416
+#, fuzzy
+msgid "Toggle zoom on focus shortcut"
+msgstr "Växla följ läge kort"
-#: src/gtk/connected-device.ui:277
-msgid "Quickly toggle between two predefined distances."
-msgstr "Växla snabbt mellan två fördefinierade avstånd."
+#: src/gtk/connected-device.ui:417
+#, fuzzy
+msgid "Quickly toggle zoom on focus mode."
+msgstr "Växla snabbt följ läge."
-#: src/gtk/connected-device.ui:305
+#: src/gtk/connected-device.ui:445
msgid "Toggle follow mode shortcut"
msgstr "Växla följ läge kort"
-#: src/gtk/connected-device.ui:306
+#: src/gtk/connected-device.ui:446
msgid "Quickly toggle follow mode."
msgstr "Växla snabbt följ läge."
-#: src/gtk/connected-device.ui:341 src/gtk/connected-device.ui:347
+#: src/gtk/connected-device.ui:481 src/gtk/connected-device.ui:487
msgid "Advanced Settings"
msgstr "Avancerade inställningar"
-#: src/gtk/connected-device.ui:350
+#: src/gtk/connected-device.ui:490
msgid "Find optimal display config"
msgstr "Hitta optimal konfiguration till skärmen"
-#: src/gtk/connected-device.ui:351
+#: src/gtk/connected-device.ui:491
msgid ""
"Automatically modify the glasses display configuration for maximum "
"resolution and best scaling when plugged in."
@@ -294,41 +398,29 @@ msgstr ""
"Ändrar automatisk glasögonens skärmkonfiguration för maximal upplösning och "
"bästa skälning när den är ansluten."
-#: src/gtk/connected-device.ui:361
+#: src/gtk/connected-device.ui:501
msgid "Use highest refresh rate"
msgstr "Använd högsta uppdateringsfrekvens"
-#: src/gtk/connected-device.ui:362
+#: src/gtk/connected-device.ui:502
msgid "Refresh rate may affect performance, disable this to set it manually."
msgstr ""
"Uppdateringsfrekvens kan påverka prestanda, inaktivera detta för att ställa "
"in det manuellt."
-#: src/gtk/connected-device.ui:372
+#: src/gtk/connected-device.ui:512
msgid "Always primary display"
msgstr "Alltid primär skärm"
-#: src/gtk/connected-device.ui:373
+#: src/gtk/connected-device.ui:513
msgid "Automatically set the glasses as the primary display when plugged in."
msgstr "Ställer automatisk glasögon som primär skärm när den är ansluten."
-#: src/gtk/connected-device.ui:383
-msgid "Fast SBS mode switching"
-msgstr "Snabb SBS läge växling"
-
-#: src/gtk/connected-device.ui:384
-msgid ""
-"Switches glasses to SBS mode immediately when plugged in, if widescreen mode "
-"is on. May cause instability."
-msgstr ""
-"Växlar glasögon till SBS läge omedelbart när den är ansluten, om bredbildsläge är "
-"på. Kan orsaka instabilitet."
-
-#: src/gtk/connected-device.ui:394
+#: src/gtk/connected-device.ui:523
msgid "Movement look-ahead"
msgstr "Rörs förväntning"
-#: src/gtk/connected-device.ui:395
+#: src/gtk/connected-device.ui:524
msgid ""
"Counteracts input lag by predicting head-tracking position ahead of render "
"time. Stick with default unless virtual display drags behind your head "
@@ -337,18 +429,34 @@ msgstr ""
"Motverkar ingångsfördröjning genom förutsägelse av huvudrörelser.Behåll "
"standardinställningen om inte skärmen skakar mycket eller rörsig konstigt."
-#: src/gtk/connected-device.ui:413
+#: src/gtk/connected-device.ui:542
msgid "Default"
msgstr "Standard"
-#: src/gtk/connected-device.ui:425
+#: src/gtk/connected-device.ui:554
msgid "Text Scaling"
msgstr "Textskalning"
-#: src/gtk/connected-device.ui:426
+#: src/gtk/connected-device.ui:555
msgid "Scaling text below 1.0 will simulate a higher resolution display"
msgstr "Textskalning under 1.0 kommer att simulera en högre skärmupplösning"
+#: src/gtk/connected-device.ui:585
+msgid "Enable multi-tap detection"
+msgstr ""
+
+#: src/gtk/connected-device.ui:586
+msgid "Enables double-tap to recenter and triple-tap to recalibrate."
+msgstr ""
+
+#: src/gtk/display-distance-dialog.ui:9
+msgid "Show full range"
+msgstr ""
+
+#: src/gtk/display-distance-dialog.ui:18
+msgid "Done"
+msgstr ""
+
#: src/gtk/failed-verification.ui:13
msgid "Breezy Desktop GNOME invalid setup"
msgstr "Breezy Desktop GNOME ogiltig inställning"
@@ -397,14 +505,6 @@ msgstr ""
"Aktivera Breezy Desktop XR-effekten automatiskt när glasögon som stöds är "
"anslutna."
-#: src/gtk/no-device.ui:34
-msgid "Start in widescreen mode"
-msgstr "Starta i bredbildsläge"
-
-#: src/gtk/no-device.ui:35
-msgid "Widescreen mode is not supported for all glasses."
-msgstr "Bredbildsläge stöds inte av alla glasögon."
-
#: src/gtk/no-driver.ui:13
msgid "No driver running"
msgstr "Inget drivrutin köres"
@@ -513,3 +613,59 @@ msgstr "Tvinga Reset"
#: src/gtk/window.ui:99
msgid "About BreezyDesktop"
msgstr "Om BreezyDesktop"
+
+#~ msgid "Fast SBS mode switching"
+#~ msgstr "Snabb SBS läge växling"
+
+#~ msgid ""
+#~ "Switches glasses to SBS mode immediately when plugged in, if widescreen "
+#~ "mode is on. May cause instability."
+#~ msgstr ""
+#~ "Växlar glasögon till SBS läge omedelbart när den är ansluten, om "
+#~ "bredbildsläge är på. Kan orsaka instabilitet."
+
+#, fuzzy
+#~ msgid "Set Unfocused Displays Distance"
+#~ msgstr "Avstånd till skärmen"
+
+#~ msgid "Widescreen mode"
+#~ msgstr "Bredbildsläge"
+
+#~ msgid "Switch between flat and curved displays."
+#~ msgstr "Växla mellan platt eller böjd skärm."
+
+#~ msgid ""
+#~ "Closer appears larger, further appears smaller. Controls depth when in "
+#~ "widescreen mode."
+#~ msgstr ""
+#~ "Närmare verkar större, längre verkar mindre. Kontrollerar djupet när du "
+#~ "är i bredbildsläge."
+
+#~ msgid ""
+#~ "Combine with display distance to achieve a comfortable level of depth and "
+#~ "size."
+#~ msgstr ""
+#~ "Kombinera med skärmens avstånd för att uppnå en bekväm nivå av djup och "
+#~ "storlek."
+
+#~ msgid "Display toggle distances"
+#~ msgstr "Växla skärm-avstånd"
+
+#~ msgid ""
+#~ "Use the buttons to capture the current display distance for use with the "
+#~ "keyboard shortcut."
+#~ msgstr ""
+#~ "Använd knapparna för att fanga nuvarande skärmavståndet för användning "
+#~ "med tangentbordsgenvägar."
+
+#~ msgid "Display distance shortcut"
+#~ msgstr "Skärm avstånd genväg"
+
+#~ msgid "Quickly toggle between two predefined distances."
+#~ msgstr "Växla snabbt mellan två fördefinierade avstånd."
+
+#~ msgid "Start in widescreen mode"
+#~ msgstr "Starta i bredbildsläge"
+
+#~ msgid "Widescreen mode is not supported for all glasses."
+#~ msgstr "Bredbildsläge stöds inte av alla glasögon."
diff --git a/ui/po/uk_UA.po b/ui/po/uk_UA.po
index 4189b2f..40acb60 100644
--- a/ui/po/uk_UA.po
+++ b/ui/po/uk_UA.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-10-22 13:27-0700\n"
+"POT-Creation-Date: 2025-03-05 12:28-0800\n"
"PO-Revision-Date: 2024-08-17 10:08-0700\n"
"Last-Translator: \n"
"Language-Team: Ukrainian \n"
@@ -18,16 +18,62 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-#: src/connecteddevice.py:17
+#: src/connecteddevice.py:23
msgid ""
"Switches your glasses into side-by-side mode and doubles the width of the "
"display."
msgstr "Переключає окуляри в режим «бок о бок» і подвоює ширину дисплея."
-#: src/connecteddevice.py:18
+#: src/connecteddevice.py:24
msgid "This feature is not currently supported for your device."
msgstr "Ця функція наразі не підтримується на вашому пристрої."
+#: src/connecteddevice.py:124
+#, fuzzy
+msgid "Set Focused Display Distance"
+msgstr "Відстань дисплея"
+
+#: src/connecteddevice.py:125
+msgid "Use a closer value so the display zooms in when you look at it."
+msgstr ""
+
+#: src/connecteddevice.py:132
+#, fuzzy
+msgid "Set All Displays Distance"
+msgstr "Відстань дисплея"
+
+#: src/connecteddevice.py:133
+msgid "Use a farther value so the displays are zoomed out when you look away."
+msgstr ""
+
+#: src/connecteddevice.py:231
+msgid ""
+"Unable to add virtual displays on this machine. xdg-desktop-portal is "
+"required."
+msgstr ""
+
+#: src/connecteddevice.py:265
+#, fuzzy
+msgid "Focused display"
+msgstr "Відстань дисплея"
+
+#: src/connecteddevice.py:271
+#, fuzzy
+msgid "All displays"
+msgstr "Викривлений дисплей"
+
+#: src/displaydistancedialogcontent.py:41
+msgid "closer"
+msgstr ""
+
+#: src/displaydistancedialogcontent.py:45
+msgid "fullscreen"
+msgstr ""
+
+#: src/displaydistancedialogcontent.py:48
+msgid "farther"
+msgstr ""
+
#: src/licensedialogcontent.py:63
msgid "Paid Tier Status"
msgstr "Статус платного рівня"
@@ -36,7 +82,7 @@ msgstr "Статус платного рівня"
msgid "Feature Availability"
msgstr "Статус функцій"
-#: src/licensefeaturerow.py:15 src/shortcutdialog.py:107
+#: src/licensefeaturerow.py:15 src/shortcutdialog.py:104
msgid "Disabled"
msgstr "Вимкнено"
@@ -165,127 +211,185 @@ msgid "Enables the Breezy Desktop XR effect."
msgstr "Включає ефект Breezy Desktop XR."
#: src/gtk/connected-device.ui:55
-msgid "Widescreen mode"
-msgstr "Режим широкого екрану"
+msgid "Zoom on focus"
+msgstr ""
-#: src/gtk/connected-device.ui:66
+#: src/gtk/connected-device.ui:56
+msgid ""
+"Automatically move a display closer when you look at it.\n"
+"Set your preferred focused and unfocused distances in the Adjustments "
+"section.\n"
+" "
+msgstr ""
+
+#: src/gtk/connected-device.ui:69
msgid "Follow mode"
msgstr "Режим слідування"
-#: src/gtk/connected-device.ui:67
-msgid "Keep the virtual display near the center of your view."
+#: src/gtk/connected-device.ui:70
+#, fuzzy
+msgid "Keep the focused display near the center of your view."
msgstr "Зберігае віртуальний дисплей поблизу центру вашого зору."
-#: src/gtk/connected-device.ui:77
-msgid "Curved display"
-msgstr "Викривлений дисплей"
+#: src/gtk/connected-device.ui:80 src/gtk/no-device.ui:34
+msgid "Disable physical displays"
+msgstr ""
-#: src/gtk/connected-device.ui:78
-msgid "Switch between flat and curved displays."
-msgstr "Переключается між плоскими і викривленими дисплеями."
+#: src/gtk/connected-device.ui:81 src/gtk/no-device.ui:35
+msgid ""
+"Automatically disable all physical displays when the XR effect is enabled."
+msgstr ""
#: src/gtk/connected-device.ui:91
+#, fuzzy
+msgid "Virtual displays"
+msgstr "Викривлений дисплей"
+
+#: src/gtk/connected-device.ui:103
+#, fuzzy
+msgid "Rearrange displays"
+msgstr "Викривлений дисплей"
+
+#: src/gtk/connected-device.ui:115
+msgid "1080p"
+msgstr ""
+
+#: src/gtk/connected-device.ui:116
+msgid "1440p"
+msgstr ""
+
+#: src/gtk/connected-device.ui:140
msgid "Adjustments"
msgstr "Налаштування"
-#: src/gtk/connected-device.ui:94
-msgid "Display distance"
+#: src/gtk/connected-device.ui:143
+#, fuzzy
+msgid "Display distances"
msgstr "Відстань дисплея"
-#: src/gtk/connected-device.ui:95
-msgid ""
-"Closer appears larger, further appears smaller. Controls depth when in "
-"widescreen mode."
+#: src/gtk/connected-device.ui:144
+msgid "Set how close you want displays to appear."
msgstr ""
-"Чим ближче, тим більший. Чим далі, тим менший. Керує глибиною при "
-"використанні режиму широкого екрана."
-#: src/gtk/connected-device.ui:123
-msgid "Display size"
-msgstr "Розмір дисплея"
-
-#: src/gtk/connected-device.ui:124
-msgid ""
-"Combine with display distance to achieve a comfortable level of depth and "
-"size."
-msgstr ""
-"Поєднуйте з відстанню дисплея, щоб досягти комфортного рівня глибини і "
-"розміру."
-
-#: src/gtk/connected-device.ui:152
-msgid "Display toggle distances"
-msgstr "Перемикання відстані дисплея"
-
-#: src/gtk/connected-device.ui:153
-msgid ""
-"Use the buttons to capture the current display distance for use with the "
-"keyboard shortcut."
-msgstr ""
-"Використовуйте кнопки, щоб зафіксувати поточну відстань дисплея для "
-"використання з сполученням клавіш."
-
-#: src/gtk/connected-device.ui:178
+#: src/gtk/connected-device.ui:199
msgid "Follow threshold"
msgstr "Поріг слідування"
-#: src/gtk/connected-device.ui:179
+#: src/gtk/connected-device.ui:200
msgid "How far away you can look before the display follows."
msgstr ""
"Як далеко ви можете відвернути ваш взор, перш ніж дисплей почне слідувати за "
"вами."
-#: src/gtk/connected-device.ui:209 src/gtk/connected-device.ui:215
+#: src/gtk/connected-device.ui:223
+#, fuzzy
+msgid "Display angling"
+msgstr "Розмір дисплея"
+
+#: src/gtk/connected-device.ui:224
+msgid ""
+"When there are multiple displays, choose how they should angle towards you."
+msgstr ""
+
+#: src/gtk/connected-device.ui:238
+msgid "Automatic"
+msgstr ""
+
+#: src/gtk/connected-device.ui:239
+msgid "Side-angled"
+msgstr ""
+
+#: src/gtk/connected-device.ui:240
+msgid "Top-angled"
+msgstr ""
+
+#: src/gtk/connected-device.ui:241
+msgid "Flat"
+msgstr ""
+
+#: src/gtk/connected-device.ui:251
+#, fuzzy
+msgid "Display spacing"
+msgstr "Розмір дисплея"
+
+#: src/gtk/connected-device.ui:252
+msgid "Put empty space between displays, when there are multiple."
+msgstr ""
+
+#: src/gtk/connected-device.ui:282
+msgid "Viewport horizontal offset"
+msgstr ""
+
+#: src/gtk/connected-device.ui:283
+msgid ""
+"By default, the viewport will center on the primary display. Use this slider "
+"to move the viewport to the left or right."
+msgstr ""
+
+#: src/gtk/connected-device.ui:312
+msgid "Viewport vertical offset"
+msgstr ""
+
+#: src/gtk/connected-device.ui:313
+msgid ""
+"By default, the viewport will center on the primary display. Use this slider "
+"to move the viewport up or down."
+msgstr ""
+
+#: src/gtk/connected-device.ui:349 src/gtk/connected-device.ui:355
msgid "Keyboard Shortcuts"
msgstr "Сполучення клавіш"
-#: src/gtk/connected-device.ui:218
+#: src/gtk/connected-device.ui:358
msgid "XR Effect on/off shortcut"
msgstr ""
-#: src/gtk/connected-device.ui:219
+#: src/gtk/connected-device.ui:359
msgid ""
"Quickly enable or disable the XR Effect. You may need to enable the effect "
"manually once in order to enable the shortcut."
msgstr ""
-#: src/gtk/connected-device.ui:238 src/gtk/connected-device.ui:267
-#: src/gtk/connected-device.ui:296 src/gtk/connected-device.ui:325
+#: src/gtk/connected-device.ui:378 src/gtk/connected-device.ui:407
+#: src/gtk/connected-device.ui:436 src/gtk/connected-device.ui:465
msgid "Change"
msgstr "Змінити"
-#: src/gtk/connected-device.ui:247
+#: src/gtk/connected-device.ui:387
msgid "Re-center display shortcut"
msgstr "Сполучення клавіш для центрування дисплея"
-#: src/gtk/connected-device.ui:248
+#: src/gtk/connected-device.ui:388
msgid "Pin the virtual display to the current position."
msgstr "Фіксувати віртуальний дисплей у поточній позиції."
-#: src/gtk/connected-device.ui:276
-msgid "Display distance shortcut"
-msgstr "Сполучення клавіш для відстані дисплея"
+#: src/gtk/connected-device.ui:416
+#, fuzzy
+msgid "Toggle zoom on focus shortcut"
+msgstr "Сполучення клавіш для перемикання режиму слідування"
-#: src/gtk/connected-device.ui:277
-msgid "Quickly toggle between two predefined distances."
-msgstr "Швидко перемикатися між двома попередньо визначеними відстанями."
+#: src/gtk/connected-device.ui:417
+#, fuzzy
+msgid "Quickly toggle zoom on focus mode."
+msgstr "Швидко перемикати режим слідування."
-#: src/gtk/connected-device.ui:305
+#: src/gtk/connected-device.ui:445
msgid "Toggle follow mode shortcut"
msgstr "Сполучення клавіш для перемикання режиму слідування"
-#: src/gtk/connected-device.ui:306
+#: src/gtk/connected-device.ui:446
msgid "Quickly toggle follow mode."
msgstr "Швидко перемикати режим слідування."
-#: src/gtk/connected-device.ui:341 src/gtk/connected-device.ui:347
+#: src/gtk/connected-device.ui:481 src/gtk/connected-device.ui:487
msgid "Advanced Settings"
msgstr "Додаткові налаштування"
-#: src/gtk/connected-device.ui:350
+#: src/gtk/connected-device.ui:490
msgid "Find optimal display config"
msgstr "Знайти оптимальну конфігурацію дисплея"
-#: src/gtk/connected-device.ui:351
+#: src/gtk/connected-device.ui:491
msgid ""
"Automatically modify the glasses display configuration for maximum "
"resolution and best scaling when plugged in."
@@ -293,41 +397,29 @@ msgstr ""
"Автоматично змінює конфігурацію дисплея окулярів для максимальної роздільної "
"здатності і найкращого масштабування при підключенні."
-#: src/gtk/connected-device.ui:361
+#: src/gtk/connected-device.ui:501
msgid "Use highest refresh rate"
msgstr "Використовувати найвищу частоту оновлення"
-#: src/gtk/connected-device.ui:362
+#: src/gtk/connected-device.ui:502
msgid "Refresh rate may affect performance, disable this to set it manually."
msgstr ""
"Частота оновлення може вплинути на продуктивність, вимкніть це, щоб "
"встановити її вручну."
-#: src/gtk/connected-device.ui:372
+#: src/gtk/connected-device.ui:512
msgid "Always primary display"
msgstr "Завжди основний дисплей"
-#: src/gtk/connected-device.ui:373
+#: src/gtk/connected-device.ui:513
msgid "Automatically set the glasses as the primary display when plugged in."
msgstr "Автоматично встановлює окуляри як основний дисплей при підключенні."
-#: src/gtk/connected-device.ui:383
-msgid "Fast SBS mode switching"
-msgstr "Швидке перемикання режиму SBS"
-
-#: src/gtk/connected-device.ui:384
-msgid ""
-"Switches glasses to SBS mode immediately when plugged in, if widescreen mode "
-"is on. May cause instability."
-msgstr ""
-"Переключає окуляри в режим SBS відразу після підключення, якщо режим "
-"широкого екрана увімкнено. Може викликати нестабільність."
-
-#: src/gtk/connected-device.ui:394
+#: src/gtk/connected-device.ui:523
msgid "Movement look-ahead"
msgstr "Прогнозування руху"
-#: src/gtk/connected-device.ui:395
+#: src/gtk/connected-device.ui:524
msgid ""
"Counteracts input lag by predicting head-tracking position ahead of render "
"time. Stick with default unless virtual display drags behind your head "
@@ -338,18 +430,34 @@ msgstr ""
"віртуальний дисплей відстає від рухів вашої голови, випереджає або дуже "
"тремтить."
-#: src/gtk/connected-device.ui:413
+#: src/gtk/connected-device.ui:542
msgid "Default"
msgstr "За замовчуванням"
-#: src/gtk/connected-device.ui:425
+#: src/gtk/connected-device.ui:554
msgid "Text Scaling"
msgstr ""
-#: src/gtk/connected-device.ui:426
+#: src/gtk/connected-device.ui:555
msgid "Scaling text below 1.0 will simulate a higher resolution display"
msgstr ""
+#: src/gtk/connected-device.ui:585
+msgid "Enable multi-tap detection"
+msgstr ""
+
+#: src/gtk/connected-device.ui:586
+msgid "Enables double-tap to recenter and triple-tap to recalibrate."
+msgstr ""
+
+#: src/gtk/display-distance-dialog.ui:9
+msgid "Show full range"
+msgstr ""
+
+#: src/gtk/display-distance-dialog.ui:18
+msgid "Done"
+msgstr ""
+
#: src/gtk/failed-verification.ui:13
msgid "Breezy Desktop GNOME invalid setup"
msgstr "Невірна настройка Breezy Desktop GNOME"
@@ -397,15 +505,6 @@ msgid ""
"connected."
msgstr ""
-#: src/gtk/no-device.ui:34
-#, fuzzy
-msgid "Start in widescreen mode"
-msgstr "Режим широкого екрану"
-
-#: src/gtk/no-device.ui:35
-msgid "Widescreen mode is not supported for all glasses."
-msgstr ""
-
#: src/gtk/no-driver.ui:13
msgid "No driver running"
msgstr "Жоден драйвер не запущений"
@@ -514,3 +613,57 @@ msgstr "Скинути"
#: src/gtk/window.ui:99
msgid "About BreezyDesktop"
msgstr "Про BreezyDesktop"
+
+#~ msgid "Fast SBS mode switching"
+#~ msgstr "Швидке перемикання режиму SBS"
+
+#~ msgid ""
+#~ "Switches glasses to SBS mode immediately when plugged in, if widescreen "
+#~ "mode is on. May cause instability."
+#~ msgstr ""
+#~ "Переключає окуляри в режим SBS відразу після підключення, якщо режим "
+#~ "широкого екрана увімкнено. Може викликати нестабільність."
+
+#, fuzzy
+#~ msgid "Set Unfocused Displays Distance"
+#~ msgstr "Відстань дисплея"
+
+#~ msgid "Widescreen mode"
+#~ msgstr "Режим широкого екрану"
+
+#~ msgid "Switch between flat and curved displays."
+#~ msgstr "Переключается між плоскими і викривленими дисплеями."
+
+#~ msgid ""
+#~ "Closer appears larger, further appears smaller. Controls depth when in "
+#~ "widescreen mode."
+#~ msgstr ""
+#~ "Чим ближче, тим більший. Чим далі, тим менший. Керує глибиною при "
+#~ "використанні режиму широкого екрана."
+
+#~ msgid ""
+#~ "Combine with display distance to achieve a comfortable level of depth and "
+#~ "size."
+#~ msgstr ""
+#~ "Поєднуйте з відстанню дисплея, щоб досягти комфортного рівня глибини і "
+#~ "розміру."
+
+#~ msgid "Display toggle distances"
+#~ msgstr "Перемикання відстані дисплея"
+
+#~ msgid ""
+#~ "Use the buttons to capture the current display distance for use with the "
+#~ "keyboard shortcut."
+#~ msgstr ""
+#~ "Використовуйте кнопки, щоб зафіксувати поточну відстань дисплея для "
+#~ "використання з сполученням клавіш."
+
+#~ msgid "Display distance shortcut"
+#~ msgstr "Сполучення клавіш для відстані дисплея"
+
+#~ msgid "Quickly toggle between two predefined distances."
+#~ msgstr "Швидко перемикатися між двома попередньо визначеними відстанями."
+
+#, fuzzy
+#~ msgid "Start in widescreen mode"
+#~ msgstr "Режим широкого екрану"
diff --git a/ui/po/zh_CN.po b/ui/po/zh_CN.po
index 0f14f64..3faee5c 100644
--- a/ui/po/zh_CN.po
+++ b/ui/po/zh_CN.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-10-22 13:27-0700\n"
+"POT-Creation-Date: 2025-03-05 12:28-0800\n"
"PO-Revision-Date: 2024-08-02 20:55-0700\n"
"Last-Translator: \n"
"Language-Team: Chinese (simplified) \n"
@@ -16,16 +16,62 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: src/connecteddevice.py:17
+#: src/connecteddevice.py:23
msgid ""
"Switches your glasses into side-by-side mode and doubles the width of the "
"display."
msgstr "切换到并排模式,并将显示宽度翻倍。"
-#: src/connecteddevice.py:18
+#: src/connecteddevice.py:24
msgid "This feature is not currently supported for your device."
msgstr "您的设备目前不支援此功能。"
+#: src/connecteddevice.py:124
+#, fuzzy
+msgid "Set Focused Display Distance"
+msgstr "显示距离"
+
+#: src/connecteddevice.py:125
+msgid "Use a closer value so the display zooms in when you look at it."
+msgstr ""
+
+#: src/connecteddevice.py:132
+#, fuzzy
+msgid "Set All Displays Distance"
+msgstr "显示距离"
+
+#: src/connecteddevice.py:133
+msgid "Use a farther value so the displays are zoomed out when you look away."
+msgstr ""
+
+#: src/connecteddevice.py:231
+msgid ""
+"Unable to add virtual displays on this machine. xdg-desktop-portal is "
+"required."
+msgstr ""
+
+#: src/connecteddevice.py:265
+#, fuzzy
+msgid "Focused display"
+msgstr "显示距离"
+
+#: src/connecteddevice.py:271
+#, fuzzy
+msgid "All displays"
+msgstr "曲面显示"
+
+#: src/displaydistancedialogcontent.py:41
+msgid "closer"
+msgstr ""
+
+#: src/displaydistancedialogcontent.py:45
+msgid "fullscreen"
+msgstr ""
+
+#: src/displaydistancedialogcontent.py:48
+msgid "farther"
+msgstr ""
+
#: src/licensedialogcontent.py:63
msgid "Paid Tier Status"
msgstr "订阅状态"
@@ -34,7 +80,7 @@ msgstr "订阅状态"
msgid "Feature Availability"
msgstr "功能状态"
-#: src/licensefeaturerow.py:15 src/shortcutdialog.py:107
+#: src/licensefeaturerow.py:15 src/shortcutdialog.py:104
msgid "Disabled"
msgstr "已禁用"
@@ -163,176 +209,245 @@ msgid "Enables the Breezy Desktop XR effect."
msgstr "启用 Breezy Desktop XR 效果。"
#: src/gtk/connected-device.ui:55
-msgid "Widescreen mode"
-msgstr "宽屏模式"
+msgid "Zoom on focus"
+msgstr ""
-#: src/gtk/connected-device.ui:66
+#: src/gtk/connected-device.ui:56
+msgid ""
+"Automatically move a display closer when you look at it.\n"
+"Set your preferred focused and unfocused distances in the Adjustments "
+"section.\n"
+" "
+msgstr ""
+
+#: src/gtk/connected-device.ui:69
msgid "Follow mode"
msgstr "跟随模式"
-#: src/gtk/connected-device.ui:67
-msgid "Keep the virtual display near the center of your view."
+#: src/gtk/connected-device.ui:70
+#, fuzzy
+msgid "Keep the focused display near the center of your view."
msgstr "虚拟显示保持在视野中心附近。"
-#: src/gtk/connected-device.ui:77
-msgid "Curved display"
-msgstr "曲面显示"
+#: src/gtk/connected-device.ui:80 src/gtk/no-device.ui:34
+msgid "Disable physical displays"
+msgstr ""
-#: src/gtk/connected-device.ui:78
-msgid "Switch between flat and curved displays."
-msgstr "平板和曲面显示模式之间切换。"
+#: src/gtk/connected-device.ui:81 src/gtk/no-device.ui:35
+msgid ""
+"Automatically disable all physical displays when the XR effect is enabled."
+msgstr ""
#: src/gtk/connected-device.ui:91
+#, fuzzy
+msgid "Virtual displays"
+msgstr "曲面显示"
+
+#: src/gtk/connected-device.ui:103
+#, fuzzy
+msgid "Rearrange displays"
+msgstr "曲面显示"
+
+#: src/gtk/connected-device.ui:115
+msgid "1080p"
+msgstr ""
+
+#: src/gtk/connected-device.ui:116
+msgid "1440p"
+msgstr ""
+
+#: src/gtk/connected-device.ui:140
msgid "Adjustments"
msgstr "调整"
-#: src/gtk/connected-device.ui:94
-msgid "Display distance"
+#: src/gtk/connected-device.ui:143
+#, fuzzy
+msgid "Display distances"
msgstr "显示距离"
-#: src/gtk/connected-device.ui:95
-msgid ""
-"Closer appears larger, further appears smaller. Controls depth when in "
-"widescreen mode."
-msgstr "距离近看起来大,距离远看起来小。调整使用宽屏模式时的深度。"
+#: src/gtk/connected-device.ui:144
+msgid "Set how close you want displays to appear."
+msgstr ""
-#: src/gtk/connected-device.ui:123
-msgid "Display size"
-msgstr "显示大小"
-
-#: src/gtk/connected-device.ui:124
-msgid ""
-"Combine with display distance to achieve a comfortable level of depth and "
-"size."
-msgstr "可以跟显示距离一起配合来实现舒适的深度和大小。"
-
-#: src/gtk/connected-device.ui:152
-msgid "Display toggle distances"
-msgstr "显示切换距离"
-
-#: src/gtk/connected-device.ui:153
-msgid ""
-"Use the buttons to capture the current display distance for use with the "
-"keyboard shortcut."
-msgstr "使用按钮记住当时的显示距离,以设成键盘快捷键。"
-
-#: src/gtk/connected-device.ui:178
+#: src/gtk/connected-device.ui:199
msgid "Follow threshold"
msgstr "跟随触发值"
-#: src/gtk/connected-device.ui:179
+#: src/gtk/connected-device.ui:200
msgid "How far away you can look before the display follows."
msgstr "在显示内容跟随前您可以看多远。"
-#: src/gtk/connected-device.ui:209 src/gtk/connected-device.ui:215
+#: src/gtk/connected-device.ui:223
+#, fuzzy
+msgid "Display angling"
+msgstr "显示大小"
+
+#: src/gtk/connected-device.ui:224
+msgid ""
+"When there are multiple displays, choose how they should angle towards you."
+msgstr ""
+
+#: src/gtk/connected-device.ui:238
+msgid "Automatic"
+msgstr ""
+
+#: src/gtk/connected-device.ui:239
+msgid "Side-angled"
+msgstr ""
+
+#: src/gtk/connected-device.ui:240
+msgid "Top-angled"
+msgstr ""
+
+#: src/gtk/connected-device.ui:241
+msgid "Flat"
+msgstr ""
+
+#: src/gtk/connected-device.ui:251
+#, fuzzy
+msgid "Display spacing"
+msgstr "显示大小"
+
+#: src/gtk/connected-device.ui:252
+msgid "Put empty space between displays, when there are multiple."
+msgstr ""
+
+#: src/gtk/connected-device.ui:282
+msgid "Viewport horizontal offset"
+msgstr ""
+
+#: src/gtk/connected-device.ui:283
+msgid ""
+"By default, the viewport will center on the primary display. Use this slider "
+"to move the viewport to the left or right."
+msgstr ""
+
+#: src/gtk/connected-device.ui:312
+msgid "Viewport vertical offset"
+msgstr ""
+
+#: src/gtk/connected-device.ui:313
+msgid ""
+"By default, the viewport will center on the primary display. Use this slider "
+"to move the viewport up or down."
+msgstr ""
+
+#: src/gtk/connected-device.ui:349 src/gtk/connected-device.ui:355
msgid "Keyboard Shortcuts"
msgstr "键盘快捷键"
-#: src/gtk/connected-device.ui:218
+#: src/gtk/connected-device.ui:358
msgid "XR Effect on/off shortcut"
msgstr "XR效果 开/关 快捷键"
-#: src/gtk/connected-device.ui:219
+#: src/gtk/connected-device.ui:359
msgid ""
"Quickly enable or disable the XR Effect. You may need to enable the effect "
"manually once in order to enable the shortcut."
msgstr "快速启用或禁用 XR 效果。您可能需要先手动启用一次该效果,才能设此快捷键"
-#: src/gtk/connected-device.ui:238 src/gtk/connected-device.ui:267
-#: src/gtk/connected-device.ui:296 src/gtk/connected-device.ui:325
+#: src/gtk/connected-device.ui:378 src/gtk/connected-device.ui:407
+#: src/gtk/connected-device.ui:436 src/gtk/connected-device.ui:465
msgid "Change"
msgstr "更改"
-#: src/gtk/connected-device.ui:247
+#: src/gtk/connected-device.ui:387
msgid "Re-center display shortcut"
msgstr "重新居中显示快捷键"
-#: src/gtk/connected-device.ui:248
+#: src/gtk/connected-device.ui:388
msgid "Pin the virtual display to the current position."
msgstr "将虚拟显示固定在当前位置。"
-#: src/gtk/connected-device.ui:276
-msgid "Display distance shortcut"
-msgstr "显示距离快捷键"
+#: src/gtk/connected-device.ui:416
+#, fuzzy
+msgid "Toggle zoom on focus shortcut"
+msgstr "切换跟随模式快捷键"
-#: src/gtk/connected-device.ui:277
-msgid "Quickly toggle between two predefined distances."
-msgstr "快速地在两个预定的距离之间切换。"
+#: src/gtk/connected-device.ui:417
+#, fuzzy
+msgid "Quickly toggle zoom on focus mode."
+msgstr "快速切换跟随模式。"
-#: src/gtk/connected-device.ui:305
+#: src/gtk/connected-device.ui:445
msgid "Toggle follow mode shortcut"
msgstr "切换跟随模式快捷键"
-#: src/gtk/connected-device.ui:306
+#: src/gtk/connected-device.ui:446
msgid "Quickly toggle follow mode."
msgstr "快速切换跟随模式。"
-#: src/gtk/connected-device.ui:341 src/gtk/connected-device.ui:347
+#: src/gtk/connected-device.ui:481 src/gtk/connected-device.ui:487
msgid "Advanced Settings"
msgstr "高级设定"
-#: src/gtk/connected-device.ui:350
+#: src/gtk/connected-device.ui:490
msgid "Find optimal display config"
msgstr "寻找最佳显示设定"
-#: src/gtk/connected-device.ui:351
+#: src/gtk/connected-device.ui:491
msgid ""
"Automatically modify the glasses display configuration for maximum "
"resolution and best scaling when plugged in."
msgstr "连接时,可以自动修改眼镜显示设定以表现出最大解析度和最佳的对比。"
-#: src/gtk/connected-device.ui:361
+#: src/gtk/connected-device.ui:501
msgid "Use highest refresh rate"
msgstr "使用最高刷新率"
-#: src/gtk/connected-device.ui:362
+#: src/gtk/connected-device.ui:502
msgid "Refresh rate may affect performance, disable this to set it manually."
msgstr "刷新率可能会影响性能,禁用此功能即可手动设置。"
-#: src/gtk/connected-device.ui:372
+#: src/gtk/connected-device.ui:512
msgid "Always primary display"
msgstr "每次设置为主要显示"
-#: src/gtk/connected-device.ui:373
+#: src/gtk/connected-device.ui:513
msgid "Automatically set the glasses as the primary display when plugged in."
msgstr "连接时,自动将眼镜设置为主要显示。"
-#: src/gtk/connected-device.ui:383
-msgid "Fast SBS mode switching"
-msgstr "快速并排模式切换"
-
-#: src/gtk/connected-device.ui:384
-msgid ""
-"Switches glasses to SBS mode immediately when plugged in, if widescreen mode "
-"is on. May cause instability."
-msgstr ""
-"连接时,如果宽屏模式开启,眼镜会立即切换到 并排模式。这可能会导致不稳定。"
-
-#: src/gtk/connected-device.ui:394
+#: src/gtk/connected-device.ui:523
msgid "Movement look-ahead"
msgstr "移动预测"
-#: src/gtk/connected-device.ui:395
+#: src/gtk/connected-device.ui:524
msgid ""
"Counteracts input lag by predicting head-tracking position ahead of render "
"time. Stick with default unless virtual display drags behind your head "
"movements, jumps ahead, or is very shaky."
msgstr ""
-"透过预测头部追踪位置,提前于渲染时间进行预测来抵消输入延迟。"
-"除非虚拟显示滞后于头部,提前跳动或非常抖动,请尽量使用默认设置。"
+"透过预测头部追踪位置,提前于渲染时间进行预测来抵消输入延迟。除非虚拟显示滞后"
+"于头部,提前跳动或非常抖动,请尽量使用默认设置。"
-#: src/gtk/connected-device.ui:413
+#: src/gtk/connected-device.ui:542
msgid "Default"
msgstr "默认"
-#: src/gtk/connected-device.ui:425
+#: src/gtk/connected-device.ui:554
msgid "Text Scaling"
msgstr "字体大小比例"
-#: src/gtk/connected-device.ui:426
+#: src/gtk/connected-device.ui:555
msgid "Scaling text below 1.0 will simulate a higher resolution display"
msgstr "字体缩放小于1.0,将模拟解析度更高的显示效果"
+#: src/gtk/connected-device.ui:585
+msgid "Enable multi-tap detection"
+msgstr ""
+
+#: src/gtk/connected-device.ui:586
+msgid "Enables double-tap to recenter and triple-tap to recalibrate."
+msgstr ""
+
+#: src/gtk/display-distance-dialog.ui:9
+msgid "Show full range"
+msgstr ""
+
+#: src/gtk/display-distance-dialog.ui:18
+msgid "Done"
+msgstr ""
+
#: src/gtk/failed-verification.ui:13
msgid "Breezy Desktop GNOME invalid setup"
msgstr "Breezy Desktop GNOME 无效设置"
@@ -379,14 +494,6 @@ msgid ""
"connected."
msgstr "当支援的设备已连接,将BREEZY DESKTOP XR效果自动启动"
-#: src/gtk/no-device.ui:34
-msgid "Start in widescreen mode"
-msgstr "使用宽屏模式以启动软件"
-
-#: src/gtk/no-device.ui:35
-msgid "Widescreen mode is not supported for all glasses."
-msgstr "宽屏模式不支援每一个型号的XR眼睛"
-
#: src/gtk/no-driver.ui:13
msgid "No driver running"
msgstr "未运行驱动程序"
@@ -490,3 +597,52 @@ msgstr "强制重置"
#: src/gtk/window.ui:99
msgid "About BreezyDesktop"
msgstr "关于 Breezy Desktop"
+
+#~ msgid "Fast SBS mode switching"
+#~ msgstr "快速并排模式切换"
+
+#~ msgid ""
+#~ "Switches glasses to SBS mode immediately when plugged in, if widescreen "
+#~ "mode is on. May cause instability."
+#~ msgstr ""
+#~ "连接时,如果宽屏模式开启,眼镜会立即切换到 并排模式。这可能会导致不稳定。"
+
+#, fuzzy
+#~ msgid "Set Unfocused Displays Distance"
+#~ msgstr "显示距离"
+
+#~ msgid "Widescreen mode"
+#~ msgstr "宽屏模式"
+
+#~ msgid "Switch between flat and curved displays."
+#~ msgstr "平板和曲面显示模式之间切换。"
+
+#~ msgid ""
+#~ "Closer appears larger, further appears smaller. Controls depth when in "
+#~ "widescreen mode."
+#~ msgstr "距离近看起来大,距离远看起来小。调整使用宽屏模式时的深度。"
+
+#~ msgid ""
+#~ "Combine with display distance to achieve a comfortable level of depth and "
+#~ "size."
+#~ msgstr "可以跟显示距离一起配合来实现舒适的深度和大小。"
+
+#~ msgid "Display toggle distances"
+#~ msgstr "显示切换距离"
+
+#~ msgid ""
+#~ "Use the buttons to capture the current display distance for use with the "
+#~ "keyboard shortcut."
+#~ msgstr "使用按钮记住当时的显示距离,以设成键盘快捷键。"
+
+#~ msgid "Display distance shortcut"
+#~ msgstr "显示距离快捷键"
+
+#~ msgid "Quickly toggle between two predefined distances."
+#~ msgstr "快速地在两个预定的距离之间切换。"
+
+#~ msgid "Start in widescreen mode"
+#~ msgstr "使用宽屏模式以启动软件"
+
+#~ msgid "Widescreen mode is not supported for all glasses."
+#~ msgstr "宽屏模式不支援每一个型号的XR眼睛"
diff --git a/ui/src/breezydesktop.gresource.xml b/ui/src/breezydesktop.gresource.xml
index 843487c..37c33ba 100644
--- a/ui/src/breezydesktop.gresource.xml
+++ b/ui/src/breezydesktop.gresource.xml
@@ -2,6 +2,8 @@
gtk/connected-device.ui
+ gtk/display-distance-dialog.ui
+ gtk/display-distance-dialog-content.ui
gtk/failed-verification.ui
gtk/license-dialog.ui
gtk/license-dialog-content.ui
@@ -10,6 +12,7 @@
gtk/no-extension.ui
gtk/no-license.ui
gtk/shortcut-dialog.ui
+ gtk/virtual-display-row.ui
gtk/window.ui
diff --git a/ui/src/configmanager.py b/ui/src/configmanager.py
index 37c6b18..983d4bc 100644
--- a/ui/src/configmanager.py
+++ b/ui/src/configmanager.py
@@ -6,6 +6,7 @@ from .xrdriveripc import XRDriverIPC
class ConfigManager(GObject.GObject):
__gproperties__ = {
'breezy-desktop-enabled': (bool, 'Breezy Desktop Enabled', 'Whether Breezy Desktop is enabled', False, GObject.ParamFlags.READWRITE),
+ 'multi-tap-enabled': (bool, 'Multi-Tap Enabled', 'Whether Multi-Tap is enabled', False, GObject.ParamFlags.READWRITE),
}
_instance = None
@@ -27,6 +28,7 @@ class ConfigManager(GObject.GObject):
GObject.GObject.__init__(self)
self.ipc = XRDriverIPC.get_instance()
self.breezy_desktop_enabled = None
+ self.multi_tap_enabled = None
self._running = True
self._refresh_config()
@@ -38,6 +40,9 @@ class ConfigManager(GObject.GObject):
if self._is_breezy_desktop_enabled() != self.breezy_desktop_enabled:
self.set_property('breezy-desktop-enabled', self._is_breezy_desktop_enabled())
+ if self.config['multi_tap_enabled'] != self.multi_tap_enabled:
+ self.set_property('multi-tap-enabled', self.config['multi_tap_enabled'])
+
if self._running: threading.Timer(1.0, self._refresh_config).start()
def _is_breezy_desktop_enabled(self):
@@ -48,17 +53,26 @@ class ConfigManager(GObject.GObject):
self.config['disabled'] = False
self.config['output_mode'] = 'external_only'
self.config['external_mode'] = ['breezy_desktop']
- self.ipc.write_config(self.config)
else:
self.config['external_mode'] = []
- self.ipc.write_config(self.config)
+ self.ipc.write_config(self.config)
self.breezy_desktop_enabled = value
+ def _set_multi_tap_enabled(self, value):
+ if self.multi_tap_enabled != value:
+ self.config['multi_tap_enabled'] = value
+ self.ipc.write_config(self.config)
+ self.multi_tap_enabled = value
+
def do_set_property(self, prop, value):
if prop.name == 'breezy-desktop-enabled':
self._set_breezy_desktop_enabled(value)
+ elif prop.name == 'multi-tap-enabled':
+ self._set_multi_tap_enabled(value)
def do_get_property(self, prop):
if prop.name == 'breezy-desktop-enabled':
- return self.breezy_desktop_enabled
\ No newline at end of file
+ return self.breezy_desktop_enabled
+ elif prop.name == 'multi-tap-enabled':
+ return self.multi_tap_enabled
\ No newline at end of file
diff --git a/ui/src/connecteddevice.py b/ui/src/connecteddevice.py
index efe638e..acb867d 100644
--- a/ui/src/connecteddevice.py
+++ b/ui/src/connecteddevice.py
@@ -1,14 +1,20 @@
-from gi.repository import Gio, Gtk, GObject
+from gi.repository import Gio, GLib, Gtk, GObject
from .configmanager import ConfigManager
from .extensionsmanager import ExtensionsManager
+from .displaydistancedialog import DisplayDistanceDialog
from .license import BREEZY_GNOME_FEATURES
from .settingsmanager import SettingsManager
from .shortcutdialog import bind_shortcut_settings
from .statemanager import StateManager
+from .virtualdisplaymanager import VirtualDisplayManager
+from .virtualdisplay import is_screencast_available
+from .virtualdisplayrow import VirtualDisplayRow
from .xrdriveripc import XRDriverIPC
import gettext
+import logging
_ = gettext.gettext
+logger = logging.getLogger('breezy_ui')
@Gtk.Template(resource_path='/com/xronlinux/BreezyDesktop/gtk/connected-device.ui')
class ConnectedDevice(Gtk.Box):
@@ -19,18 +25,20 @@ class ConnectedDevice(Gtk.Box):
device_label = Gtk.Template.Child()
effect_enable_switch = Gtk.Template.Child()
- display_distance_scale = Gtk.Template.Child()
- display_distance_adjustment = Gtk.Template.Child()
- display_size_scale = Gtk.Template.Child()
- display_size_adjustment = Gtk.Template.Child()
+ disable_physical_displays_switch = Gtk.Template.Child()
+ display_zoom_on_focus_switch = Gtk.Template.Child()
follow_threshold_scale = Gtk.Template.Child()
follow_threshold_adjustment = Gtk.Template.Child()
follow_mode_switch = Gtk.Template.Child()
- widescreen_mode_switch = Gtk.Template.Child()
- widescreen_mode_row = Gtk.Template.Child()
- curved_display_switch = Gtk.Template.Child()
- set_toggle_display_distance_start_button = Gtk.Template.Child()
- set_toggle_display_distance_end_button = Gtk.Template.Child()
+ top_features_group = Gtk.Template.Child()
+ virtual_displays_row = Gtk.Template.Child()
+ add_virtual_display_menu = Gtk.Template.Child()
+ add_virtual_display_button = Gtk.Template.Child()
+ launch_display_settings_button = Gtk.Template.Child()
+ all_displays_distance_label = Gtk.Template.Child()
+ change_all_displays_distance_button = Gtk.Template.Child()
+ focused_display_distance_label = Gtk.Template.Child()
+ change_focused_display_distance_button = Gtk.Template.Child()
reassign_toggle_xr_effect_shortcut_button = Gtk.Template.Child()
toggle_xr_effect_shortcut_label = Gtk.Template.Child()
reassign_recenter_display_shortcut_button = Gtk.Template.Child()
@@ -42,44 +50,65 @@ class ConnectedDevice(Gtk.Box):
headset_as_primary_switch = Gtk.Template.Child()
use_optimal_monitor_config_switch = Gtk.Template.Child()
use_highest_refresh_rate_switch = Gtk.Template.Child()
- fast_sbs_mode_switch = Gtk.Template.Child()
movement_look_ahead_scale = Gtk.Template.Child()
movement_look_ahead_adjustment = Gtk.Template.Child()
text_scaling_scale = Gtk.Template.Child()
text_scaling_adjustment = Gtk.Template.Child()
-
+ enable_multi_tap_switch = Gtk.Template.Child()
+ monitor_wrapping_scheme_menu = Gtk.Template.Child()
+ monitor_spacing_scale = Gtk.Template.Child()
+ monitor_spacing_adjustment = Gtk.Template.Child()
+ viewport_offset_x_scale = Gtk.Template.Child()
+ viewport_offset_x_adjustment = Gtk.Template.Child()
+ viewport_offset_y_scale = Gtk.Template.Child()
+ viewport_offset_y_adjustment = Gtk.Template.Child()
def __init__(self):
super(Gtk.Box, self).__init__()
self.init_template()
self.active = True
self.all_enabled_state_inputs = [
- self.display_distance_scale,
- self.display_size_scale,
+ self.display_zoom_on_focus_switch,
+ # self.display_size_scale,
self.follow_mode_switch,
self.follow_threshold_scale,
- self.curved_display_switch,
- self.set_toggle_display_distance_start_button,
- self.set_toggle_display_distance_end_button,
- self.movement_look_ahead_scale
+ # self.curved_display_switch,
+ self.add_virtual_display_menu,
+ self.add_virtual_display_button,
+ self.change_all_displays_distance_button,
+ self.change_focused_display_distance_button,
+ self.movement_look_ahead_scale,
+ self.monitor_wrapping_scheme_menu,
+ self.monitor_spacing_scale,
+ self.viewport_offset_x_scale,
+ self.viewport_offset_y_scale
]
self.settings = SettingsManager.get_instance().settings
self.desktop_settings = SettingsManager.get_instance().desktop_settings
self.ipc = XRDriverIPC.get_instance()
+ self.virtual_display_manager = VirtualDisplayManager.get_instance()
self.extensions_manager = ExtensionsManager.get_instance()
- self.settings.bind('display-distance', self.display_distance_adjustment, 'value', Gio.SettingsBindFlags.DEFAULT)
- self.settings.bind('display-size', self.display_size_adjustment, 'value', Gio.SettingsBindFlags.DEFAULT)
+ self.settings.bind('disable-physical-displays', self.disable_physical_displays_switch, 'active', Gio.SettingsBindFlags.DEFAULT)
+ self.settings.connect('changed::display-distance', self._handle_display_distance)
+ # self.settings.bind('display-size', self.display_size_adjustment, 'value', Gio.SettingsBindFlags.DEFAULT)
self.settings.bind('follow-threshold', self.follow_threshold_adjustment, 'value', Gio.SettingsBindFlags.DEFAULT)
- self.settings.bind('widescreen-mode', self.widescreen_mode_switch, 'active', Gio.SettingsBindFlags.DEFAULT)
- self.settings.bind('curved-display', self.curved_display_switch, 'active', Gio.SettingsBindFlags.DEFAULT)
+ # self.settings.bind('widescreen-mode', self.widescreen_mode_switch, 'active', Gio.SettingsBindFlags.DEFAULT)
+ # self.settings.bind('curved-display', self.curved_display_switch, 'active', Gio.SettingsBindFlags.DEFAULT)
self.settings.bind('headset-as-primary', self.headset_as_primary_switch, 'active', Gio.SettingsBindFlags.DEFAULT)
self.settings.bind('use-optimal-monitor-config', self.use_optimal_monitor_config_switch, 'active', Gio.SettingsBindFlags.DEFAULT)
self.settings.bind('use-highest-refresh-rate', self.use_highest_refresh_rate_switch, 'active', Gio.SettingsBindFlags.DEFAULT)
- self.settings.bind('fast-sbs-mode-switching', self.fast_sbs_mode_switch, 'active', Gio.SettingsBindFlags.DEFAULT)
+ # self.settings.bind('fast-sbs-mode-switching', self.fast_sbs_mode_switch, 'active', Gio.SettingsBindFlags.DEFAULT)
self.settings.bind('look-ahead-override', self.movement_look_ahead_adjustment, 'value', Gio.SettingsBindFlags.DEFAULT)
+ self.settings.bind('monitor-spacing', self.monitor_spacing_adjustment, 'value', Gio.SettingsBindFlags.DEFAULT)
+ self.settings.bind('viewport-offset-x', self.viewport_offset_x_adjustment, 'value', Gio.SettingsBindFlags.DEFAULT)
+ self.settings.bind('viewport-offset-y', self.viewport_offset_y_adjustment, 'value', Gio.SettingsBindFlags.DEFAULT)
+ self.settings.connect('changed::monitor-wrapping-scheme', self._handle_monitor_wrapping_scheme_setting_changed)
self.desktop_settings.bind('text-scaling-factor', self.text_scaling_adjustment, 'value', Gio.SettingsBindFlags.DEFAULT)
+ self.display_zoom_on_focus_switch.connect('notify::active', self._handle_zoom_on_focus_switch_changed)
+ self.monitor_wrapping_scheme_menu.connect('changed', self._handle_monitor_wrapping_scheme_menu_changed)
+ self._handle_monitor_wrapping_scheme_setting_changed(self.settings, self.settings.get_string('monitor-wrapping-scheme'))
bind_shortcut_settings(self.get_parent(), [
[self.reassign_toggle_xr_effect_shortcut_button, self.toggle_xr_effect_shortcut_label],
@@ -88,10 +117,28 @@ class ConnectedDevice(Gtk.Box):
[self.reassign_toggle_follow_shortcut_button, self.toggle_follow_shortcut_label]
])
- self.bind_set_distance_toggle([
- self.set_toggle_display_distance_start_button,
- self.set_toggle_display_distance_end_button
- ])
+ self.change_focused_display_distance_button.connect('clicked',
+ self._on_display_distance_preset_change_button_clicked,
+ 'toggle-display-distance-start',
+ self._on_set_focused_display_distance,
+ _('Set Focused Display Distance'),
+ _('Use a closer value so the display zooms in when you look at it.'),
+ 0.2, 1.0
+ )
+ self.change_all_displays_distance_button.connect('clicked',
+ self._on_display_distance_preset_change_button_clicked,
+ 'toggle-display-distance-end',
+ self._on_set_all_displays_distance,
+ _('Set All Displays Distance'),
+ _('Use a farther value so the displays are zoomed out when you look away.'),
+ 1.0, 2.5
+ )
+ self._set_all_displays_distance(self.settings.get_double('toggle-display-distance-end'))
+ self._set_focused_display_distance(self.settings.get_double('toggle-display-distance-start'))
+
+ self.add_virtual_display_menu.set_active_id('1080p')
+ self.add_virtual_display_button.connect('clicked', self._on_add_virtual_display)
+ self.launch_display_settings_button.connect('clicked', self._launch_display_settings)
self.state_manager = StateManager.get_instance()
self.state_manager.bind_property('follow-mode', self.follow_mode_switch, 'active', GObject.BindingFlags.DEFAULT)
@@ -104,16 +151,46 @@ class ConnectedDevice(Gtk.Box):
self.config_manager = ConfigManager.get_instance()
self.config_manager.connect('notify::breezy-desktop-enabled', self._handle_enabled_config)
+ self.config_manager.bind_property('multi-tap-enabled', self.enable_multi_tap_switch, 'active', Gio.SettingsBindFlags.DEFAULT)
+ self.enable_multi_tap_switch.connect('notify::active', lambda widget, param: self.config_manager.set_property('multi-tap-enabled', widget.get_active()))
self.use_optimal_monitor_config_switch.connect('notify::active', self._refresh_use_optimal_monitor_config)
+ self._handle_switch_enabled_state(self.effect_enable_switch, None)
+ self._handle_display_distance(self.settings, self.settings.get_double('display-distance'))
self._handle_enabled_features(self.state_manager, None)
self._handle_device_supports_sbs(self.state_manager, None)
self._handle_enabled_config(None, None)
self._refresh_use_optimal_monitor_config(self.use_optimal_monitor_config_switch, None)
self.extensions_manager.connect('notify::breezy-enabled', self._handle_enabled_config)
- self.connect("destroy", self._on_widget_destroy)
+ self.virtual_display_manager.connect('notify::displays', self._on_virtual_displays_update)
+ self._on_virtual_displays_update(self.virtual_display_manager, None)
+
+ self.virtual_displays_by_pid = {}
+
+ self._settings_displays_app_info = None
+
+ for appinfo in Gio.AppInfo.get_all():
+ if appinfo.get_id() == 'gnome-display-panel.desktop':
+ self._settings_displays_app_info = appinfo
+ break
+
+ def _handle_zoom_on_focus_switch_changed(self, widget, param):
+ display_distance = self.settings.get_double('display-distance')
+ toggle_display_distance_end = self.settings.get_double('toggle-display-distance-end')
+ toggle_display_distance_start = self.settings.get_double('toggle-display-distance-start')
+ is_zoom_on_focus_already_enabled = display_distance < toggle_display_distance_end
+ if widget.get_active() and not is_zoom_on_focus_already_enabled:
+ self.settings.set_double('display-distance', toggle_display_distance_start)
+ elif not widget.get_active() and is_zoom_on_focus_already_enabled:
+ self.settings.set_double('display-distance', toggle_display_distance_end)
+
+ def _handle_monitor_wrapping_scheme_setting_changed(self, settings, val):
+ self.monitor_wrapping_scheme_menu.set_active_id(val)
+
+ def _handle_monitor_wrapping_scheme_menu_changed(self, widget):
+ self.settings.set_string('monitor-wrapping-scheme', widget.get_active_id())
def _handle_enabled_features(self, state_manager, val):
enabled_breezy_features = [feature for feature in state_manager.get_property('enabled-features-list') if feature in BREEZY_GNOME_FEATURES]
@@ -125,9 +202,9 @@ class ConnectedDevice(Gtk.Box):
def _handle_device_supports_sbs(self, state_manager, val):
if not state_manager.get_property('device-supports-sbs'):
self.settings.set_boolean('widescreen-mode', False)
- self.widescreen_mode_switch.set_sensitive(state_manager.get_property('device-supports-sbs'))
- subtitle = self.widescreen_mode_subtitle if state_manager.get_property('device-supports-sbs') else self.widescreen_mode_not_supported_subtitle
- self.widescreen_mode_row.set_subtitle(subtitle)
+ # self.widescreen_mode_switch.set_sensitive(state_manager.get_property('device-supports-sbs'))
+ # subtitle = self.widescreen_mode_subtitle if state_manager.get_property('device-supports-sbs') else self.widescreen_mode_not_supported_subtitle
+ # self.widescreen_mode_row.set_subtitle(subtitle)
def _handle_enabled_config(self, object, val):
enabled = self.config_manager.get_property('breezy-desktop-enabled') and self.extensions_manager.get_property('breezy-enabled')
@@ -135,6 +212,9 @@ class ConnectedDevice(Gtk.Box):
self.effect_enable_switch.set_active(enabled)
def _handle_switch_enabled_state(self, switch, param):
+ GLib.idle_add(self._handle_switch_enabled_state_gui, switch, param)
+
+ def _handle_switch_enabled_state_gui(self, switch, param):
requesting_enabled = switch.get_active()
# never turn off the extension, disabling the effect is done via configs only
@@ -145,12 +225,17 @@ class ConnectedDevice(Gtk.Box):
for widget in self.all_enabled_state_inputs:
widget.set_sensitive(requesting_enabled)
+
+ if not is_screencast_available():
+ self.virtual_displays_row.set_subtitle(
+ _("Unable to add virtual displays on this machine. xdg-desktop-portal is required."))
+ self.add_virtual_display_button.set_sensitive(False)
+ self.add_virtual_display_menu.set_sensitive(False)
if requesting_enabled:
self._refresh_follow_mode(self.follow_mode_switch, None)
def _refresh_follow_mode(self, switch, param):
- self.follow_threshold_scale.set_sensitive(switch.get_active())
if (self.state_manager.get_property('follow-mode') == switch.get_active()):
return
@@ -167,18 +252,90 @@ class ConnectedDevice(Gtk.Box):
def set_device_name(self, name):
self.device_label.set_markup(f"{name}")
+
+ def _handle_display_distance(self, *args):
+ display_distance = self.settings.get_double('display-distance')
+ toggle_display_distance_end = self.settings.get_double('toggle-display-distance-end')
+
+ should_zoom_on_focus_be_enabled = display_distance < toggle_display_distance_end
+ if self.display_zoom_on_focus_switch.get_active() != should_zoom_on_focus_be_enabled:
+ self.display_zoom_on_focus_switch.set_active(should_zoom_on_focus_be_enabled)
+
+ def _set_focused_display_distance(self, distance):
+ self.focused_display_distance_label.set_markup(f"{_("Focused display")}: {distance}")
+ self.settings.set_double('toggle-display-distance-start', distance)
+
+ self.display_zoom_on_focus_switch.set_sensitive(distance != self.settings.get_double('toggle-display-distance-end'))
+
+ def _set_all_displays_distance(self, distance):
+ self.all_displays_distance_label.set_markup(f"{_("All displays")}: {distance}")
+ self.settings.set_double('toggle-display-distance-end', distance)
+ self.display_zoom_on_focus_switch.set_active(False)
+ self.display_zoom_on_focus_switch.set_sensitive(distance != self.settings.get_double('toggle-display-distance-start'))
+
+ def _on_display_distance_preset_change_button_clicked(self, widget, settings_key, on_save_callback, title, subtitle, lower_limit, upper_limit):
+ dialog = DisplayDistanceDialog(settings_key, on_save_callback, title, subtitle, lower_limit, upper_limit)
+ dialog.set_transient_for(widget.get_ancestor(Gtk.Window))
+ dialog.present()
- def bind_set_distance_toggle(self, widgets):
- for widget in widgets:
- widget.connect('clicked', lambda *args, widget=widget: on_set_display_distance_toggle(widget))
- reload_display_distance_toggle_button(widget)
-
- def _on_widget_destroy(self, widget):
- self.state_manager.unbind_property('follow-mode', self.follow_mode_switch, 'active')
- self.settings.unbind('display-distance', self.display_distance_adjustment, 'value')
- self.settings.unbind('display-size', self.display_size_adjustment, 'value')
- self.settings.unbind('follow-threshold', self.follow_threshold_adjustment, 'value')
- self.settings.unbind('widescreen-mode', self.widescreen_mode_switch, 'active')
+ def _on_set_all_displays_distance(self, prev_distance, distance):
+ focused_display_distance = self.settings.get_double('toggle-display-distance-start')
+ all_displays_distance = self.settings.get_double('toggle-display-distance-end')
+ if (distance < focused_display_distance):
+ self._set_focused_display_distance(distance)
+
+ self._set_all_displays_distance(distance)
+
+ if prev_distance == focused_display_distance:
+ self.settings.set_double('display-distance', prev_distance)
+
+ def _on_set_focused_display_distance(self, prev_distance, distance):
+ focused_display_distance = self.settings.get_double('toggle-display-distance-start')
+ all_displays_distance = self.settings.get_double('toggle-display-distance-end')
+ if (distance > all_displays_distance):
+ self._set_all_displays_distance(distance)
+
+ self._set_focused_display_distance(distance)
+
+ def _on_add_virtual_display(self, *args):
+ resolution = self.add_virtual_display_menu.get_active_id()
+ logger.info(f"Adding virtual display {resolution}")
+
+ width = 1920
+ height = 1080
+ if resolution == '1440p':
+ width = 2560
+ height = 1440
+
+ self.virtual_display_manager.create_virtual_display(width, height, 60)
+
+ def _on_virtual_displays_update(self, virtual_display_manager, val):
+ GLib.idle_add(self._on_virtual_displays_update_gui, virtual_display_manager)
+
+ def _on_virtual_displays_update_gui(self, virtual_display_manager):
+ effect_enabled = self.effect_enable_switch.get_active()
+ virtual_displays_present = len(virtual_display_manager.displays) > 0
+ self.launch_display_settings_button.set_visible(
+ self._settings_displays_app_info is not None and virtual_displays_present
+ )
+ self.monitor_wrapping_scheme_menu.set_sensitive(effect_enabled and virtual_displays_present)
+ self.monitor_spacing_scale.set_sensitive(effect_enabled and virtual_displays_present)
+
+ for pid, child in self.virtual_displays_by_pid.items():
+ self.top_features_group.remove(child)
+
+ new_displays_by_pid = {}
+ for display in virtual_display_manager.displays:
+ child = self.virtual_displays_by_pid.get(
+ display['pid'],
+ VirtualDisplayRow(display['pid'], display['width'], display['height'], 60))
+ self.top_features_group.add(child)
+ new_displays_by_pid[display['pid']] = child
+
+ self.virtual_displays_by_pid = new_displays_by_pid
+
+ def _launch_display_settings(self, *args):
+ self._settings_displays_app_info.launch()
def reload_display_distance_toggle_button(widget):
distance = SettingsManager.get_instance().settings.get_double(widget.get_name())
diff --git a/ui/src/displaydistancedialog.py b/ui/src/displaydistancedialog.py
new file mode 100644
index 0000000..9f02baa
--- /dev/null
+++ b/ui/src/displaydistancedialog.py
@@ -0,0 +1,28 @@
+from gi.repository import Gtk, Gio
+from .displaydistancedialogcontent import DisplayDistanceDialogContent
+
+@Gtk.Template(resource_path='/com/xronlinux/BreezyDesktop/gtk/display-distance-dialog.ui')
+class DisplayDistanceDialog(Gtk.Dialog):
+ __gtype_name__ = 'DisplayDistanceDialog'
+
+ show_full_scale_button = Gtk.Template.Child()
+ save_button = Gtk.Template.Child()
+
+ def __init__(self, settings_key, on_save_callback, title, subtitle, lower_limit, upper_limit):
+ super(Gtk.Dialog, self).__init__()
+ self.init_template()
+
+ self.on_save_callback = on_save_callback
+ self.set_title(title)
+
+ self.content = DisplayDistanceDialogContent(settings_key, self.show_full_scale_button, self.save_button, self._on_save_callback, subtitle, lower_limit, upper_limit)
+ self.get_content_area().append(self.content)
+
+ self.show_full_scale_button.connect('clicked', self._on_show_full_scale_button_clicked)
+
+ def _on_show_full_scale_button_clicked(self, button):
+ self.show_full_scale_button.set_visible(False)
+
+ def _on_save_callback(self, prev_distance, distance):
+ self.on_save_callback(prev_distance, distance)
+ self.close()
\ No newline at end of file
diff --git a/ui/src/displaydistancedialogcontent.py b/ui/src/displaydistancedialogcontent.py
new file mode 100644
index 0000000..3b81e72
--- /dev/null
+++ b/ui/src/displaydistancedialogcontent.py
@@ -0,0 +1,58 @@
+from gi.repository import Gtk, Gio
+from .settingsmanager import SettingsManager
+
+import gettext
+
+_ = gettext.gettext
+
+
+@Gtk.Template(resource_path='/com/xronlinux/BreezyDesktop/gtk/display-distance-dialog-content.ui')
+class DisplayDistanceDialogContent(Gtk.Box):
+ __gtype_name__ = 'DisplayDistanceDialogContent'
+
+ display_distance_subtitle = Gtk.Template.Child()
+ display_distance_scale = Gtk.Template.Child()
+ display_distance_adjustment = Gtk.Template.Child()
+
+ def __init__(self, settings_key, show_full_scale_button, save_button, on_save_callback, subtitle, lower_limit, upper_limit):
+ super(Gtk.Box, self).__init__()
+ self.init_template()
+
+ self.display_distance_subtitle.set_markup(f"""{subtitle}""")
+
+ self.on_save_callback = on_save_callback
+ self.settings = SettingsManager.get_instance().settings
+ self.prev_distance = self.settings.get_double('display-distance')
+
+ self.lower_limit_orig = self.display_distance_adjustment.get_lower()
+ self.upper_limit_orig = self.display_distance_adjustment.get_upper()
+
+ self._add_marks(lower_limit, upper_limit)
+
+ self.settings.bind('display-distance', self.display_distance_adjustment, 'value', Gio.SettingsBindFlags.DEFAULT)
+
+ show_full_scale_button.connect('clicked', self._on_show_full_scale_button_clicked)
+ save_button.connect('clicked', self._on_save_button_clicked)
+
+ def _add_marks(self, lower_limit, upper_limit):
+ self.display_distance_scale.clear_marks()
+
+ if self.lower_limit_orig == lower_limit:
+ self.display_distance_scale.add_mark(self.lower_limit_orig, Gtk.PositionType.BOTTOM, _("closer"))
+ else:
+ self.display_distance_adjustment.set_lower(lower_limit)
+
+ self.display_distance_scale.add_mark(1.0, Gtk.PositionType.BOTTOM, _("fullscreen"))
+
+ if self.upper_limit_orig == upper_limit:
+ self.display_distance_scale.add_mark(self.upper_limit_orig, Gtk.PositionType.BOTTOM, _("farther"))
+ else:
+ self.display_distance_adjustment.set_upper(upper_limit)
+
+ def _on_show_full_scale_button_clicked(self, button):
+ self._add_marks(self.lower_limit_orig, self.upper_limit_orig)
+ self.display_distance_adjustment.set_lower(self.lower_limit_orig)
+ self.display_distance_adjustment.set_upper(self.upper_limit_orig)
+
+ def _on_save_button_clicked(self, button):
+ self.on_save_callback(self.prev_distance, self.display_distance_adjustment.get_value())
\ No newline at end of file
diff --git a/ui/src/gtk/connected-device.ui b/ui/src/gtk/connected-device.ui
index 26f7063..2849ef6 100644
--- a/ui/src/gtk/connected-device.ui
+++ b/ui/src/gtk/connected-device.ui
@@ -37,7 +37,7 @@
20
20
-
+
+
+ Enable multi-tap detection
+ Enables double-tap to recenter and triple-tap to recalibrate.
+
+
+ 3
+
+
+
+
diff --git a/ui/src/gtk/display-distance-dialog-content.ui b/ui/src/gtk/display-distance-dialog-content.ui
new file mode 100644
index 0000000..704b9c4
--- /dev/null
+++ b/ui/src/gtk/display-distance-dialog-content.ui
@@ -0,0 +1,37 @@
+
+
+
+
+ vertical
+ 3
+
+
+ true
+ 20
+ 20
+ 20
+
+
+
+
+ 3
+ 20
+ 20
+ 20
+ true
+ 0
+ 2
+ 350
+ false
+
+
+ 0.2
+ 2.5
+ 0.01
+ 1.05
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/src/gtk/display-distance-dialog.ui b/ui/src/gtk/display-distance-dialog.ui
new file mode 100644
index 0000000..1ac5219
--- /dev/null
+++ b/ui/src/gtk/display-distance-dialog.ui
@@ -0,0 +1,26 @@
+
+
+
+
+ 1
+ 1
+
+
+ Show full range
+ 10
+ 10
+ 10
+ 10
+
+
+
+
+ Done
+ 10
+ 10
+ 10
+ 10
+
+
+
+
\ No newline at end of file
diff --git a/ui/src/gtk/no-device.ui b/ui/src/gtk/no-device.ui
index c7d6cad..4ce401d 100644
--- a/ui/src/gtk/no-device.ui
+++ b/ui/src/gtk/no-device.ui
@@ -30,12 +30,11 @@
-
- Start in widescreen mode
- Widescreen mode is not supported for all glasses.
- 2
+
+ Disable physical displays
+ Automatically disable all physical displays when the XR effect is enabled.
-
+
3
diff --git a/ui/src/gtk/virtual-display-row.ui b/ui/src/gtk/virtual-display-row.ui
new file mode 100644
index 0000000..acb2c2f
--- /dev/null
+++ b/ui/src/gtk/virtual-display-row.ui
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+ remove-virtual-display
+ user-trash-symbolic
+ center
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/src/meson.build b/ui/src/meson.build
index 0a2b141..447c0d6 100644
--- a/ui/src/meson.build
+++ b/ui/src/meson.build
@@ -26,12 +26,23 @@ configure_file(
install_mode: 'r-xr-xr-x'
)
+configure_file(
+ input: 'virtualdisplay.in',
+ output: 'virtualdisplay',
+ configuration: conf,
+ install: true,
+ install_dir: get_option('bindir'),
+ install_mode: 'r-xr-xr-x'
+)
+
breezydesktop_sources = [
'../modules/PyXRLinuxDriverIPC/xrdriveripc.py',
'__init__.py',
'configmanager.py',
'connecteddevice.py',
'extensionsmanager.py',
+ 'displaydistancedialog.py',
+ 'displaydistancedialogcontent.py',
'failedverification.py',
'license.py',
'licensedialog.py',
@@ -47,8 +58,11 @@ breezydesktop_sources = [
'shortcutdialog.py',
'statemanager.py',
'time.py',
+ 'virtualdisplay.py',
+ 'virtualdisplaymanager.py',
'verify.py',
'window.py'
]
install_data(breezydesktop_sources, install_dir: moduledir)
+install_subdir('../lib', install_dir: moduledir)
\ No newline at end of file
diff --git a/ui/src/nodevice.py b/ui/src/nodevice.py
index b36c656..fa56bfe 100644
--- a/ui/src/nodevice.py
+++ b/ui/src/nodevice.py
@@ -10,7 +10,8 @@ class NoDevice(Gtk.Box):
__gtype_name__ = "NoDevice"
effect_enable_switch = Gtk.Template.Child()
- widescreen_mode_switch = Gtk.Template.Child()
+ disable_physical_displays_switch = Gtk.Template.Child()
+ # widescreen_mode_switch = Gtk.Template.Child()
def __init__(self):
super(Gtk.Box, self).__init__()
@@ -23,7 +24,8 @@ class NoDevice(Gtk.Box):
self.config_manager.connect('notify::breezy-desktop-enabled', self._handle_enabled_config)
self.effect_enable_switch.connect('notify::active', self._handle_switch_enabled_state)
- self.settings.bind('widescreen-mode', self.widescreen_mode_switch, 'active', Gio.SettingsBindFlags.DEFAULT)
+ # self.settings.bind('widescreen-mode', self.widescreen_mode_switch, 'active', Gio.SettingsBindFlags.DEFAULT)
+ self.settings.bind('disable-physical-displays', self.disable_physical_displays_switch, 'active', Gio.SettingsBindFlags.DEFAULT)
self._handle_enabled_config(self.config_manager, None)
@@ -41,5 +43,5 @@ class NoDevice(Gtk.Box):
self.config_manager.set_property('breezy-desktop-enabled', requesting_enabled)
- def _on_widget_destroy(self, widget):
- self.settings.unbind('widescreen-mode', self.widescreen_mode_switch, 'active')
+ # def _on_widget_destroy(self, widget):
+ # self.settings.unbind('widescreen-mode', self.widescreen_mode_switch, 'active')
diff --git a/ui/src/shortcutdialog.py b/ui/src/shortcutdialog.py
index 356c74e..4bb1e3b 100644
--- a/ui/src/shortcutdialog.py
+++ b/ui/src/shortcutdialog.py
@@ -36,9 +36,6 @@ class ShortcutDialog(Gtk.Dialog):
keycode,
state
)
- label = Gtk.accelerator_get_label(keyval, state)
-
- # hacky way to store the label, causes warnings from the WM
SettingsManager.get_instance().settings.set_strv(self.settings_key, [binding])
self.close()
diff --git a/ui/src/virtualdisplay.in b/ui/src/virtualdisplay.in
new file mode 100755
index 0000000..882b148
--- /dev/null
+++ b/ui/src/virtualdisplay.in
@@ -0,0 +1,107 @@
+#!/usr/bin/env python3
+
+# virtualdisplay.in
+#
+# Copyright 2024 Unknown
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+import logging
+import os
+import sys
+
+lib_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'lib')
+sys.path.insert(0, lib_dir)
+
+from logging.handlers import TimedRotatingFileHandler
+
+config_home = os.environ.get('XDG_CONFIG_HOME', '~/.config')
+config_dir = os.path.expanduser(config_home)
+state_home = os.environ.get('XDG_STATE_HOME', '~/.local/state')
+state_dir = os.path.expanduser(state_home)
+breezy_state_dir = os.path.join(state_dir, 'breezy_gnome')
+log_dir = os.path.join(breezy_state_dir, 'logs/ui')
+os.makedirs(log_dir, exist_ok=True)
+
+logger = logging.getLogger('breezy_ui')
+logger.setLevel(logging.INFO)
+logname = os.path.join(log_dir, "breezy_desktop.log")
+handler = TimedRotatingFileHandler(logname, when="midnight", backupCount=30)
+handler.suffix = "%Y%m%d"
+formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+handler.setFormatter(formatter)
+logger.addHandler(handler)
+
+import sys
+import argparse
+import signal
+import time
+
+VERSION = '@VERSION@'
+
+xdg_data_home = os.getenv('XDG_DATA_HOME', os.path.join(os.path.expanduser('~'), '.local', 'share'))
+appdir = os.getenv('APPDIR', xdg_data_home)
+locale_dir = os.path.join(appdir, 'locale')
+pkgdatadir = os.path.join(appdir, 'breezydesktop')
+sys.path.insert(1, pkgdatadir)
+
+import gi
+
+gi.require_version('GLib', '2.0')
+
+from gi.repository import GLib
+
+def graceful_shutdown(signum, frame):
+ global virtual_display_instance
+ global loop
+
+ if virtual_display_instance is not None:
+ virtual_display_instance.terminate()
+
+def _on_display_closed():
+ global loop
+ loop.quit()
+
+def create_display(width, height, framerate):
+ global virtual_display_instance
+
+ virtual_display_instance = VirtualDisplay(width, height, framerate, _on_display_closed)
+ virtual_display_instance.create()
+
+if __name__ == "__main__":
+ from breezydesktop import virtualdisplay
+ from breezydesktop.virtualdisplay import VirtualDisplay
+
+ global virtual_display_instance
+ global loop
+
+ parser = argparse.ArgumentParser(description="Virtual display arguments")
+ parser.add_argument("--height", type=int, required=True, help="Height of the display")
+ parser.add_argument("--width", type=int, required=True, help="Width of the display")
+ parser.add_argument("--framerate", type=int, default=60, help="Framerate of the display")
+ args = parser.parse_args()
+
+ signal.signal(signal.SIGTERM, graceful_shutdown)
+ signal.signal(signal.SIGINT, graceful_shutdown)
+
+ loop = GLib.MainLoop()
+
+ try:
+ GLib.idle_add(create_display, args.width, args.height, args.framerate)
+ loop.run()
+ except Exception as e:
+ logger.error(f"Error in main loop: {e}")
+ sys.exit(1)
\ No newline at end of file
diff --git a/ui/src/virtualdisplay.py b/ui/src/virtualdisplay.py
new file mode 100644
index 0000000..64eb478
--- /dev/null
+++ b/ui/src/virtualdisplay.py
@@ -0,0 +1,100 @@
+#!/usr/bin/python3
+
+import argparse
+import logging
+import sys
+import signal
+from .lib import pydbus
+import gi
+import time
+
+gi.require_version('Gst', '1.0')
+from gi.repository import GLib, GObject, Gst
+
+logger = logging.getLogger('breezy_ui')
+
+screen_cast_iface = 'org.gnome.Mutter.ScreenCast'
+screen_cast_session_iface = 'org.gnome.Mutter.ScreenCast.Session'
+screen_cast_stream_iface = 'org.gnome.Mutter.ScreenCast.Session'
+gst_pipeline_format = "pipewiresrc path=%u ! video/x-raw,max-framerate=%d/1,width=%d,height=%d ! fakesink sync=false"
+
+class VirtualDisplay:
+ def __init__(self, width, height, framerate, on_closed_cb):
+ self.width = width
+ self.height = height
+ self.framerate = framerate
+ self.on_closed_cb = on_closed_cb
+
+ Gst.init(None)
+
+ def _screen_cast_session(self):
+ bus = pydbus.SessionBus()
+ screen_cast = bus.get(screen_cast_iface, '/org/gnome/Mutter/ScreenCast')
+ session_path = screen_cast.CreateSession([])
+ screen_cast_session = bus.get(screen_cast_iface, session_path)
+
+ return screen_cast_session
+
+ def _on_session_closed(self):
+ self.stream = None
+ self.terminate()
+
+ def create(self):
+ session = self._screen_cast_session()
+ session.onClosed = self._on_session_closed
+ stream_path = session.RecordVirtual({
+ 'is-platform': GLib.Variant.new_boolean(True),
+ })
+ bus = pydbus.SessionBus()
+ self.stream = bus.get(screen_cast_iface, stream_path)
+
+ self.stream.onPipeWireStreamAdded = self._on_pipewire_stream_added
+
+ session.Start()
+
+ def terminate(self):
+ try:
+ if self.stream is not None:
+ self.stream.Stop()
+ except Exception as e:
+ logger.error("Failed to stop stream: %s" % e)
+
+ try:
+ if self.pipeline is not None:
+ self.pipeline.send_event(Gst.Event.new_eos())
+ self.pipeline.set_state(Gst.State.NULL)
+ except Exception as e:
+ logger.error("Failed to stop pipeline: %s" % e)
+
+ self.on_closed_cb()
+
+ def _on_message(self, bus, message):
+ type = message.type
+ logger.info("message type: %s" % type)
+ if type == Gst.MessageType.EOS:
+ self.pipeline = None
+ self.terminate()
+ elif type == Gst.MessageType.ERROR:
+ err, debug = message.parse_error()
+ logger.error("Error: %s" % err)
+ logger.error("Debug: %s" % debug)
+ self.terminate()
+
+ def _on_pipewire_stream_added(self, node_id):
+ self.pipeline = Gst.parse_launch(gst_pipeline_format % (node_id, self.framerate, self.width, self.height))
+ self.pipeline.set_state(Gst.State.PLAYING)
+ self.pipeline.get_bus().connect('message', self._on_message)
+ self.pipeline.set_state(Gst.State.PAUSED)
+
+def is_screencast_available():
+ try:
+ bus = pydbus.SessionBus()
+ # Try to get the ScreenCast interface
+ screen_cast = bus.get(screen_cast_iface, '/org/gnome/Mutter/ScreenCast')
+ return True
+ except Exception as e:
+ logger.warning(f"ScreenCast portal not available: {e}")
+ return False
+
+
+
diff --git a/ui/src/virtualdisplaymanager.py b/ui/src/virtualdisplaymanager.py
new file mode 100644
index 0000000..dd02bc1
--- /dev/null
+++ b/ui/src/virtualdisplaymanager.py
@@ -0,0 +1,122 @@
+import gi
+import json
+import os
+import signal
+import subprocess
+import time
+from pathlib import Path
+
+import logging
+logger = logging.getLogger('breezy_ui')
+
+gi.require_version('GLib', '2.0')
+from gi.repository import GLib, GObject
+
+xdg_bin_home = os.getenv('XDG_BIN_HOME', os.path.join(os.path.expanduser('~'), '.local', 'bin'))
+bindir = os.getenv('BINDIR', xdg_bin_home)
+
+class VirtualDisplayManager(GObject.GObject):
+ __gproperties__ = {
+ 'displays': (object, 'Displays', 'A list of the displays', GObject.ParamFlags.READWRITE)
+ }
+ _instance = None
+
+ @staticmethod
+ def get_instance():
+ if not VirtualDisplayManager._instance:
+ VirtualDisplayManager._instance = VirtualDisplayManager()
+
+ return VirtualDisplayManager._instance
+
+ def __init__(self):
+ GObject.GObject.__init__(self)
+
+ self.shm_path = Path("/dev/shm/breezy_virtual_displays.json")
+ self._load_displays()
+ self._prune_dead_display_processes()
+
+ GLib.timeout_add_seconds(15, self._prune_dead_display_processes)
+
+ def _process_dead(self, pid):
+ if (not os.path.exists(f"/proc/{pid}")):
+ return True
+
+ try:
+ if (os.waitpid(pid, os.WNOHANG) == (pid, 0)):
+ return True
+ except ChildProcessError:
+ # process isn't tied to the current process, it's not dead if it's still open
+ return False
+
+ return False
+
+ def _prune_dead_display_processes(self):
+ new_displays = [disp for disp in self.displays if not self._process_dead(disp['pid'])]
+ if new_displays != self.displays:
+ self.set_property('displays', new_displays)
+ self._save_processes()
+
+ return GLib.SOURCE_CONTINUE
+
+ def create_virtual_display(self, width, height, framerate):
+ try:
+ process = subprocess.Popen(
+ [f"{bindir}/virtualdisplay", "--width", str(width), "--height", str(height), "--framerate", str(framerate)],
+ start_new_session=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ text=True
+ )
+
+ if process.returncode is not None:
+ logger.error(f"Failed to create virtual display: {process.stderr.read()}")
+ return
+
+ self.displays.append({
+ 'pid': process.pid,
+ 'width': width,
+ 'height': height
+ })
+ self.set_property('displays', self.displays)
+ self._save_processes()
+ except Exception as e:
+ logger.error(f"Failed to create virtual display: {e}")
+
+ def destroy_virtual_display(self, pid: str) -> bool:
+ try:
+ # Send SIGTERM to allow graceful shutdown
+ os.killpg(pid, signal.SIGTERM)
+ self.set_property('displays', [disp for disp in self.displays if disp['pid'] != pid])
+ self._save_processes()
+ return True
+ except ProcessLookupError:
+ # Process already gone, delete pid from list
+ self.set_property('displays', [disp for disp in self.displays if disp['pid'] != pid])
+ self._save_processes()
+ return True
+ except Exception as e:
+ print(f"Failed to kill process {pid}: {e}")
+ return False
+
+ def _save_processes(self):
+ with open(self.shm_path, 'w') as f:
+ json.dump(self.displays, f)
+
+ def _load_displays(self):
+ displays = []
+ if self.shm_path.exists():
+ try:
+ with open(self.shm_path, 'r') as f:
+ displays = json.load(f)
+ except Exception:
+ displays = []
+
+ self.set_property('displays', displays)
+
+ def do_set_property(self, prop, value):
+ if prop.name == 'displays':
+ self.displays = value
+
+ def do_get_property(self, prop):
+ if prop.name == 'displays':
+ return self.displays
\ No newline at end of file
diff --git a/ui/src/virtualdisplayrow.py b/ui/src/virtualdisplayrow.py
new file mode 100644
index 0000000..ef4593a
--- /dev/null
+++ b/ui/src/virtualdisplayrow.py
@@ -0,0 +1,31 @@
+from gi.repository import Adw, Gtk
+from .virtualdisplaymanager import VirtualDisplayManager
+
+import gettext
+
+_ = gettext.gettext
+
+@Gtk.Template(resource_path='/com/xronlinux/BreezyDesktop/gtk/virtual-display-row.ui')
+class VirtualDisplayRow(Adw.ActionRow):
+ __gtype_name__ = "VirtualDisplayRow"
+
+ remove_virtual_display_button = Gtk.Template.Child()
+
+ def __init__(self, pid, width, height, framerate):
+ super(Adw.ActionRow, self).__init__()
+ self.init_template()
+ self.pid = pid
+
+ icon = Gtk.Image.new_from_icon_name("video-display-symbolic")
+
+ # padding around the icon
+ self.add_prefix(Gtk.Label(label=" "))
+ self.add_prefix(icon)
+ self.add_prefix(Gtk.Label(label=" "))
+
+ self.set_subtitle(f"{width} x {height}")
+
+ self.remove_virtual_display_button.connect('clicked', self._remove_virtual_display)
+
+ def _remove_virtual_display(self, widget):
+ VirtualDisplayManager.get_instance().destroy_virtual_display(self.pid)
\ No newline at end of file
diff --git a/ui/src/window.py b/ui/src/window.py
index 502f7dc..330e743 100644
--- a/ui/src/window.py
+++ b/ui/src/window.py
@@ -22,6 +22,7 @@ from .extensionsmanager import ExtensionsManager
from .license import BREEZY_GNOME_FEATURES
from .licensedialog import LicenseDialog
from .statemanager import StateManager
+from .settingsmanager import SettingsManager
from .connecteddevice import ConnectedDevice
from .failedverification import FailedVerification
from .nodevice import NoDevice
@@ -42,14 +43,6 @@ class BreezydesktopWindow(Gtk.ApplicationWindow):
def __init__(self, skip_verification, **kwargs):
super().__init__(**kwargs)
-
- self._skip_verification = skip_verification
-
- self.state_manager = StateManager.get_instance()
- self.state_manager.connect('device-update', self._handle_state_update)
- self.state_manager.connect('notify::license-action-needed', self._handle_state_update)
- self.state_manager.connect('notify::license-present', self._handle_state_update)
- self.state_manager.connect('notify::enabled-features-list', self._handle_state_update)
self.connected_device = ConnectedDevice()
self.failed_verification = FailedVerification()
@@ -57,6 +50,16 @@ class BreezydesktopWindow(Gtk.ApplicationWindow):
self.no_driver = NoDriver()
self.no_extension = NoExtension()
self.no_license = NoLicense()
+
+ self._skip_verification = skip_verification
+
+ self.settings = SettingsManager.get_instance().settings
+ self.state_manager = StateManager.get_instance()
+ self.state_manager.connect('device-update', self._handle_state_update)
+ self.state_manager.connect('notify::license-action-needed', self._handle_state_update)
+ self.state_manager.connect('notify::license-present', self._handle_state_update)
+ self.state_manager.connect('notify::enabled-features-list', self._handle_state_update)
+ self.settings.connect('changed::debug-no-device', self._handle_settings_update)
self.license_action_needed_button.connect('clicked', self._on_license_button_clicked)
self.missing_breezy_features_button.connect('clicked', self._on_license_button_clicked)
@@ -67,6 +70,9 @@ class BreezydesktopWindow(Gtk.ApplicationWindow):
self.connect("destroy", self._on_window_destroy)
+ def _handle_settings_update(self, settings_manager, key):
+ self._handle_state_update(self.state_manager, None)
+
def _handle_state_update(self, state_manager, val):
GLib.idle_add(self._handle_state_update_gui, state_manager)
@@ -79,7 +85,10 @@ class BreezydesktopWindow(Gtk.ApplicationWindow):
for child in self.main_content:
self.main_content.remove(child)
- if not self._skip_verification and not verify_installation():
+ if self.settings.get_boolean('debug-no-device'):
+ self.main_content.append(self.connected_device)
+ self.connected_device.set_device_name('Fake device')
+ elif not self._skip_verification and not verify_installation():
self.main_content.append(self.failed_verification)
elif not ExtensionsManager.get_instance().is_installed():
self.main_content.append(self.no_extension)