From 6cddd6989120b75d097ea750507774d20b24ca80 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Wed, 20 May 2026 18:24:33 -0400 Subject: [PATCH] fix(display): skip mirror/extend if already in requested state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mirror_displays() now checks CGDisplayMirrorsDisplay() for each secondary before calling CGBeginDisplayConfiguration — avoids a needless display reconfiguration (and potential flicker) when already mirrored. extend_displays() already had this check; no change needed there. --- resources/bin/display_control | Bin 101794 -> 101874 bytes scripts/display_control.m | 11 +++++++++++ 2 files changed, 11 insertions(+) diff --git a/resources/bin/display_control b/resources/bin/display_control index d9ec6502faea1fd8420d5de762c9851d5df1615b..ff657cdc4bef4fa46d039640bf3df1f61f8cbd9e 100755 GIT binary patch delta 7540 zcmdT{d0bRSwyx@pMuQCsg0c&;2?#0*8bY(Qb|NatfLYw5DDDK}f`)WE$b?SQiTy5_ ziy9+3Cc$N5N6d&b8cE;<#>52jViG5r1hc)1@g>HWap*j;=c`){ww=jue)H$MzplD< zzB=dBsjp5|-#WNgbA7L7SMZpvgpd)Gkh}0E1PwxL*HMjlHT}ID!Ije!ppW4=9nCrk z(F>RLIRSZD9DRp_Bu_}s%?a?I&e1eC>M!g7s&}I+)g0CfJwTgtxNfmqw^@kJdzR{j zSMx&YIN?Ixgdlw`*U-8(n5?j;hYI>Um5`jDOt%UT=f@;Iq#|T8A!dK5J+zY$Hn;*M z1f>!3M7$k!gmein=10;5I8fI;MaX^j^ie{8euDpT#qPgnIkHBc{AqX7uuFS-g|vc9 zs&83c;G+nrgFW+`h{E2DEjwnO3ln;m2PYf=A4ZG8QB&Qo(Ag%S(`Z#c6wY3mMq9>P z=ynik`Dh_>MS{=Akfeu33v*Y*nNG0w1XMNsL{}RKL+K)>U@_e6G+bpX&^H$08?Dv7 za8u8eZw0xP*_5O%4I!O|n`q+24fT4&{CQfV+9S@bpeL9z9n!gYc8MDYP8>&S+gQgn6ffI z|3&1i2Wd&Nq57k-JX~uDqi+iI5%OoFyh8?C4(XEc$Cc5F9b<)SWkIGrvQ8Jg5Tk8V z_c@kzMq5djG#ec?)m;i*O*|jM$cM0&u;2y|IYuawt>0m!^!*QNDHMRk(9vmV0|cVZ zu$R?vW`?0lSCh-z)`HsZ8HNts&Im$Gtke2LZMXE&NJ1D|>nm%u)wEFyh;iG?(wV*% zm&;`}v{~nL)%4MDC1135GlZZR7R1X>M;tdG}rTT42m&HxYJYzJa9 z=mvc=*Hd_4!H7ZT{%IH>LYc6m(0|Ktl=3;642R@N9_p*cB+b=Fu}f0iBTB_EgX`C@ z6Zk$G&i%G|xLf2_ex02HQi5k>?pbf<=GGDx*|%6Jtl*P_9)#L5|F9bze1e1UgXMY0 zVratHal)%*K`~9nnvSK5+ND5f=!UP@? zX*dR_q%V%8TowQpqOH17>eR7zLrrzV?X`{`^w<@bT*6pjPZec`Vjr<2`Lc z?wYx#63?FVmJ8ivar;C@cOktHg2EjsIs zJ37p0fx#Oi7=yY<9JP344r{KK!?Guc2tSks=3jw=Cxw53?4Ee1p_v(ZZrEeePFepp zxy{l#p>*vuy&x}zx&|-(jZSLR8L)w~7xGD!G9#-x3==Y1Z%2!>mSCmJ5vQN<>DuVw zU;6<_?11V;LA!4J*u#*eBd9F3&F{HfaOlJ`fTfRxS?lgKr80F(?Jm}3J==(vq~uVY z2c!Um zTKxuusP%31E8+6`d2^l_E;|q5&h>an%Q+O~0WIWEf(Mk(p)?QZZlQWZBwZuy+YoNr z0Tx+?K+F2tA*N)@uHe|cGS{SerPHrgkC>mOq6$!^hUMH{W%+3T;7sEH<0^ufp!fB23q1#q2)3 z3bOv!s4MJ*uZ55bEn%^Rmf~2g(NYlWkBGAIFJrB}3k0wuPj2)b8jxvw1^S>elxf%) zmDcBuF}*7kdvupPg8C`E7)yDKrJda13a5$Z+S5XAMV#(_-sA9LRH;`9n=7KmJOF|1 zI{o0OmB#)itm;(Zc*UfMzaj5ys#}S!9;Vo?tuqXbx?gW(o58C7MsQUWYs)ZW#P^c0 zpfZ*&63msMIt$BeIU~EEwp=(;8KEr%hUA+gbXPW}EW{UJGu73y55Ycv`77sa5e|7N z8;H?TYeXB{M21ER&pn<+uL$owUQC~DiQQzQ;gjX1!jXuCpW`UB8rabo4uTNJWZ~V- zA*NgS&%{B7r8hL8FPQaFNu^}7c^(6^4=9B85m$r8Ezkh#FAxhfTtgbK4QYJGHQMB8 z)%%9)sSWXf#z2d0d4CVg#g@QQtM!1s z5jwXdhx~wfu=Dx3A8)bT$oLi$Lew{e;aiO%cCXF>tQ|UkE3Dl*J0#Vsvx!@Rt*v?5 zCz&Rde1wpyNcy6XSrwzPfgs&*;f<=432&j-HJ*KKy2hWE>v!b(UAgX->-XjQ1EH@f zeEw&0yH~Eikn6AH`Ww0Km+PP8`lejplItkY=o&vxu4CmoPOcN=I?1OcdD{^hRRFA)=Xrf?$TI7UzDpmTM<6F{qynT;f6p$j6YbXgqKwG(Kvx2B!Lg_^bQ4;k7 zC}xx{lpj%IRYYB^BFfDudr)3S`3mJH6pflFN1{Zii7E}H2;~_yQFjB2(-7rU4bjX* z*^2ftlrvyqN&d{-ii%}bvq~S&-?(W*%gwfM>L*XI(mnAOzc(i;gxrp}N84s1O!l*zGihd=z>_clT{c*#~T`DHJ;!%P0eOJ)g=-;nT)5jua$ zyyR_Ovdv3w^pan=LpBj|=njC8BVKX~mvMjNPrH}Q4i*GF)UQOSo)bvr^3VjPddgGa z^BxW$OZfAkm;9Kg0aU7l`#aYP`Yx3iTSxuH0#rh8r;4Tumpk{<)RyY5*+0*%WJQbg z_Ir~XXm?OplpG*A#*RunOjZbA>t_UXVM8HwVrCVdE-{_boB*TO?cONvp!9RWkrzgz zaE-SruKNj(!ra3$dRwBo44<4`|!U1+|6$2im<4bH3b?)v>CSkuuVi^Z{~|V;V4WlI+d%TpNtW;(KH~i zRPU60i1S=~WNTARWa|NCWPg>I5=|3SQHl0a@nP0VPO`5SqsP%vVq-K7R~eJ+3uTd3 zix;A4m}*6meVzY$&wAK?6*rZ(C4}u)g<|KO_S6kqvhP1k^b}Y%B zA(o7zQ`Fr__7IKu%s4uB+;9zPXlf5{ZB{PnCw_Y8Fvz{3#3{=GdZ$Jso*zeNskbKE z)f#bh49%mTiVw#ixTa+LRk13Drm5PJ?VpRkkD>GEv*JJuO;%k^wmZa>SQAG-1tJp)-Ot{ie&_K~AM&Fr<*cdhJODf>1BO6cfQYL7IxlOAo=>ej>gZl&P; zW3>u*03JF7I{36`Xl8muyH@f+pv0}0uRpC-lK=?=vq1+3mN5kKxyuzSL5BsBs3wnT zsR_}*f#i08+;WiqRQqBKaIQV9bu*mwwiEkZkb5VR)6zr?K*0`z^Jb?HeLrKTY@$5} zwu9_E3V*KSB+C`=X2lfmMT^=!6X3tdii+#>hGIEA^eC7)2v)ABeje-)lkTM)40iM# zYpG4M2eO%lil2?A!6pPc#3II#Sw!IYVhxs#>$B?I>A~V?$C!g@0vktkTbg|U*xKZ)<3k(ux_HjU|a$-^nWRs&hSiqFT}-|S)}{dk%x%86KO1!ckz7zHP*1y#)_wMEW_{VGLgMF{)9hRC4M)7 zhWb9CcjDus`$e-jGMPR@XNd=r=`6z}c<5bAoV_N!GlsP{@^&0+SMqigYj5$;nXPwT zo~L*AZYKi@jrsjNF(rjY(tL4F3Js-qi>uiyL#$1qIpO1B%Vwzc)jJ3Gj7)+f!yX}C zW}3m`0A6GKndV+EE!8ypFfl!q29LnSr9n3I&$LtJsrjk&H1%~P?#^IGv_lL@qjhwH zcpwddtQ6l!qxpU%_^*-41#zijKst>dZv=F>W--fchjtm~$~(8?#YO3KiXYDWzRARi zJB}l9nfO9FO{Hq_LOR_`uZgQC(RliiXrDx*vOF12lvlx_t>T^!#$Xl3W2K1s{TLJ# zeC_1R;J`9mnM9w7wo}ru)V-?&+VoJu3pj}v&A$Gpt%Z({A)y!{eu&msdu zcs|GXh~uYWq~qfHX>=8RPQ1uo+r{imx`398yEAD*$S*KvJas9PhETuxdhCVB5Amhp z@Lw$6%AynLW-)a-ovM+cJ*O5=r%(JF7nnaN#nv1e=*Pah*!LeRe-%-MP|+e{1ot;`-5=U7;=XgIHm|)e z=X^n4QOSZ4yQe!g{P!ypzVKZdv#qlGn$q9}(s3MR z+Ss!6c**pHik>O#ICM^hkA%+Y0p_vO={4EovnlIfr`rcgocmpS4K~dE=l*&3hqdY(mITO2`nr3BiC6=V5e1U&?u}NbwbQMtGA1zCDUh z65>@pmy05nO%~`y0g`1(PH|C0_U!`YTKSW$YzMm3kN!py=u)KG+Gttas0iL5I38rr&FY*I|#A5a)v2A zC28S9f67~TcJ+kFr`CM1_t4Ximnqq$lc=|ORcWX$Vl8C3&U7^Xu4>*s?TuKM+@Q$I zN2J9JhZ?)ZU0vCuGdag%-s+ItvHUg3>dc>pX*W?niBfFK(?S=5QZGd*rPNJXlg2T!wwFrr-Xy5(m>N2Q53dbV>K`mA8G~#L2wH|FD2*Q_+;z<3;X4hzaCzad zV3!dsxB6RURC$8#!;wnI$|zf;#?uZh#Okc*c*Cd-=C!MD{s)gpyUtXdDoiwt)J!<$ zapx+9g};KS&GI%6O4mc^)qMc$mJ3#ArAJNI#;2<*PZLv(U&+1wN=`$`ib!JPe%1zP zNraY*mS$*ef>PqJG)=Lzo2oa7v7@xMV~XX1sb(%{EXIR*$Hv+Y$Gi*bI}zNp-yA;- zNX+k$I!H{%JZ^5Z@OcERaZ$An0=9ndPe1^6X&2tyYIQ5MTbjBmeLi1RWiv81OVbFk zMG%8(MW}|}|3(P0idNwL+7|nnU*`u>9T(`CKM-?;c&Kpg@5+5E&5OK3(Kew7l5pg0 zyQLA<3>rJ^&g`*HZa38q(k2_N)fbj7KCebX!Zf(NynLL=jMIx}p4I-9b^Em{3?Y3{ zd2i+L2nsH2j63J2SL1=J*Oi}EnkOB=8OP4M`*;3`S`DPSvhmlQUonDfK@=OY+G2zc ztKFl_Ts3;8UU>WzB>WrJmBP~?7l7T;0BifzHWMG$S69~mng+c%-ku`m zPip+X2DecyS1hY1%A2&UkRHNI{;7>xO%@!gLRlgT0jwt#b@iB0FMw8$ptILDzUT8n;V0MzMCp=}`p8|jG|q0Xt>aUU*Y@M3 z_8|g*b_PH<0O3litqQ=d3bxGw&|3mpt3gtP-&MN>mzVS{l7c&qUkOCRV|C7R=d{|D ze?2nDco|b=j zK7M2w2!80~{!1$x#~HIB%HH)8M*j^J@AWBe>Qq}P?t*3UJT z!3_LsP^N51rVEs%8)8fk@LbnYupMkulwBJ}8rZYdOX^81vfNqIBdP80dv1#k%;n5SgNi(2*bF~`3n9h*uZg>a}f1o!Qs2b;k?Ch zNpQTXc`H@i!aD?hSi>u;R1*e@WmDv=B97Q=6 z%~OrbI44!9(zDr2E0yRiN##2bAk$#t8?zsCzA?{f{Xwlir1cG2e^~2}X#F3wzESIs zYkiZ}pVE4_*1xRvr?vi1Aw((OlBFEl5}k5WLkL3Y8>7>DgVu*=y%9Zsnuk1boHk$D z`jbA7m;RFg@x}{&{_ruDg%1Wj%5eUxgc90FXe&-{0@2Yw$+S>b3R_E8ZPXFz6x!El z@p>Z7LVE`79NG_Pi3XxCMO%rs8|`JZcC^cAUbJflVz`MmS|Wz~BqAM>i2g@3LkJ0p zM4J{u^iQDeYW}`;JZ&yGm!xB5HFWGU?{v*8e5y?Emg)=*hHmP{!60NM9OoZ99Vz0| zV~d~mrU`nNpC)4kz28rF`{^Toxz_umHPH* z*1dxsY<9O>d7i}Um~l6?Hg9=*N3Ki0tDbg5851;{L`50MA5QC(ujDBa-AH(NLpJgb zPdCeJEn~ zi%JsHvk|FWe1oEpA=xNxv++hqw2xf=p_+y9!kxIwm7^tQngR`yyn_%+|A+3SyOyn} zS~E#Hkr;LAz;9pQz&~_##)RgFOG9)COQC=(PDkT!u8==*Xq+ZzibLo}BVF<}78_3^ zA|H@@)lky=#(A@+q1xERS`4DUo_1X7+H=RS<2|FXy&(3n4;N)z2KZ{7BnTGqaT-#W25*;yN zn`UE)r*G@DW4`m$)v8}|#i!SG_H7M4)(0B9+F|6;8cce%@nW_siH@>e{erlBQ%DP; zRdZ%RhdM=WF%BZ@)QSH!s-2RFSbC&7SnefM?(M>ysvmT`OHW*Bl<;39cYUm&g_e4I*J)KuuD&^uy)-cX@9m3^N~huiK5P_zt+e0#}cpP961 zPMGBu?tqaFTCF)J`JLmq-gvz6Jn1xUS>@@P=;whUqe1X^M_}Ord=z|F!S{_}fOD)m z4Nkz(|FuYCwkv`!1bW_wO#fo@;Ugcb@RR%4@262B5i0yfNj5^=D^K3(44j+1!+cwE9eOsp=^Xb`>>2%a> zLD|FH=`@NZq|%s(gW&$$B==q&Cii;B%PsrZ%v73ZKz1BtwW)M`7-#U!CN0Zh@=10! zl}@Ky*`PG~BE5&bltwp<%mafKOfccH#PTuV8LnI!y+}vzOb? zj`+8Jpy_MudOF=Z6zi@JS`%$&M>8NjpZzt1#$+#+dyPoz#_G{MR~5T}^tuHn|t|OTG6oF;3#+4PuPnrh4xtKM%W}Nr%xQCS_4`oQ#>SCB*|$ zUt734&o!A9XVDlsfi2FWMKqE9o>MWb1+TbB$Z64_a-WJ!!;ep&Cbzr56~?Y-(Ge-3 zoQ2`~@LwC+^v;Pc3S1k9PjcPVof$Wdw$MR!>Cfi#%c_obkEc87YPKbtn(1=(Y&ISY}EuB9~Bt?bZt-E#tL?50*x6YBJD<`&rLw2_pp0%>9DY;@H63EPI?=v z=k{!3>vECGkFu6rI)g4eBjwRwsIHGNT>-tFe$NUE=vev%TZPxie-KiyT@ks+9xC(u zvo7Jt9j;64WC1njG-291o2#AQ^Lsv?A;vH8@pRI63oj8kV|@iM-NY;t=|l8sc9Op~ zv#3e*Ub=>@n?%$44~^x_OOt3c4O;}eI`b9$kh;Um*_Fw3Jbj9V+)fLcGuwe&&M(LYEeM29*$4>j~kw9Q%_trVQ= zIg?S1L(T4~p()FDPK6iz**Uc%!+`9c*F}(yu7cZt4CW|s>t)IT(FRr)y=_ZsO zU?Y3|^v4;3KH#S}vJY#h83habxrSc+|6fnf66Gqq7thildP5NXWDs2wMDH3vqn@rC z01)!5pn0Nb&#@r7J&5iS^sRatH_Cu|I#$r4eul>UK$`zb%nlM*z{~07G)`I9j{ncM zM=Ig%`zdKY**=5zXN#F?B{iG9n@*BQyp9ZU<)pBechh*={qUI#;yBJdQhkNLa7ay6` zIPKlZAE|c^KhS#o{R5c|dgGRa>v8v|#O|A8`uID;Gr4l!+gXX;veL92qu>9f`%w9z xWpDMe^-j7pesIOO!=I#m*FAIDvl;DK=CrUcx8~GsAO1>W+0Ls+uDp5pe*jMU+{*v} diff --git a/scripts/display_control.m b/scripts/display_control.m index b71743e..43f6d4d 100644 --- a/scripts/display_control.m +++ b/scripts/display_control.m @@ -31,6 +31,17 @@ static int mirror_displays(void) { CGDirectDisplayID mainID = CGMainDisplayID(); + // Idempotency: if every secondary is already mirroring mainID, nothing to do. + CGDisplayCount alreadyMirrored = 0; + for (CGDisplayCount i = 0; i < numOnline; i++) { + if (onlineDspys[i] != mainID && CGDisplayMirrorsDisplay(onlineDspys[i]) == mainID) + alreadyMirrored++; + } + if (alreadyMirrored == numOnline - 1) { + printf("Displays already mirrored.\n"); + return 0; + } + CGDisplayConfigRef config; CGError err = CGBeginDisplayConfiguration(&config); if (err != kCGErrorSuccess) {