From fccc4c43e6cd59b2dadf0e13334b4bc6fe09d2d7 Mon Sep 17 00:00:00 2001 From: Artem Bochkarev Date: Tue, 16 Oct 2018 17:41:39 +0700 Subject: [PATCH] linux-menubar: check for dbus-service (AppMenu) instead of desktop env filters fixed PY-32237 GUI tests Unable to register window, error: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name com.canonical.AppMenu.Registrar was not provided by any .service files fixed IDEA-200273 Exceptions: GlobalMenuLinux - Unable to register window and AppMenu-service can't register xid --- bin/linux/libdbm64.so | Bin 38096 -> 34328 bytes native/LinuxGlobalMenu/DbusMenuWrapper.c | 85 +++++++++++- native/LinuxGlobalMenu/DbusMenuWrapper.h | 5 +- .../openapi/wm/impl/GlobalMenuLinux.java | 129 ++++++++++++------ .../intellij/openapi/wm/impl/IdeMenuBar.java | 32 ++++- .../wm/impl/ToolWindowManagerImpl.java | 3 + .../util/resources/misc/registry.properties | 2 - 7 files changed, 199 insertions(+), 57 deletions(-) diff --git a/bin/linux/libdbm64.so b/bin/linux/libdbm64.so index f46f96e1496dd6acd120a1964df3d563474125c9..e3368f40339c99a0617bbeca6ebd1d7f1315a690 100755 GIT binary patch literal 34328 zcmdsgd3;sXz3<-VB)AEI1QHMwaWf}C29O{QU=9#C(Ew=(2u_C#Cj%xq@#Gu^2SfpD z8qv=LfVZ!uYAv-Bw-uWR<))z4+gkI!-!<&B&rXis_wM_= zKi-D3*ZPg?w|;Bbd$0Y=+P9ZgEcKbDp%1^Y&>&QNp2UAotGY5~Wkaumyr;48d>T0s$hmMMkIDX%b(mQZ45LnsSGg++iiB(`+)}(5WRs zgKGFYtg7lwrzk$1l9xy2iC8`JyXFaSK)OWf)2WvG9OP){fAz>#j8&?; zUeqlYI{f%8Td~?0d!~K+zkKgL-`npUcy!5*d%l-_%P-z$5hL-t6hEpt2frU0X;&KO znMaP~rq6!xU+>sK+GY6By;tBDz)v5GkXeRb5WjMTtU$U_<(X9C_uYzH*1h+}e~d84 z%xmA@{g)AD`DJIXTix>FuWnj9{=gsay>(I9FHWUJf`452hZV7{)t{dnZulVQw--ka z-}J*ZB{w%c*|l_A{-gP07dE}Rc)fM!H|`t0>Vr4?|N8H5{=on6tk+yc4aoY9p~e$q zlF=LBkWtAf0bK>h4Tk>{95Wa`7oB`C{6#7B(+qo%a-U04Zg~p)lPU1`q`=>r!k&T@ z{1MnVSiP2}@WUtQ;DhmxPQkw=h5qR&_@7T`0-%H-(h+Tp{Krt>VE(){g`Njf;O9V(?KK|o$M_AV|1|uj zuMuuB&cBn~2$lc$6z%u~=!5CMJw<(6M0;f#Zxl+!GnIbYGRhck)X!E3m4p=kw-x^k zg@0Y(2hPvyg`Js3BwsRKr1(D&e#iJN z_^VX8GgY}ul(sJ*9c5%1%@;_-Hxzz~s+V8YYn#IVMA_LlO(HnXc|4`~=N3u$tim4w zNd1`;B!03?jBI7kQB_~vrjIN950vBC-aKwm`aen9io{+M0mnx8c z=ka}|zhCK310RpsO8<7HUsca|PxO;a<1wZ9v}8AoP^hsr(iZB7)kI^VkP&KVZfiC| z<<-kW_2Fo^vAH7_j#e*U+!ARESJ%|Gge7foN~msg4HeY1G~W!yD>sI!l!nDEH60z{ z4r60STYI#*E!Kc?QDohXp}M9ULk%^}Ek-onwxl-Ru__$h7>*i^q1Kw_wopqX(jICH zZvqTjXj4tBt|`=3(;7}Vs{)DUlJ0U}bnAzT*= z#oMCc27sP2+!97zG+Yx4FNf-?NF=s261}>u-WXVqZJj8)ETYeR!ViKuHYD%55FZ zjp$~fx=33a9UzRXMIkG~n^alKTe3tAw6}**>v$Vkllh|I*2u;%3~mY6bc7{sW!rLe z!V2_3c(S>^B^;`$AIxWtFVKmMIw*+J#dNiVM9yg}_O#D(DtRzW(5u;*3>52VM4tM} z(LWM?Z`D14?o7j z2CSf=6*aZt77diOaUQAHU^&`w5DStjQoAJv-$$c0TeQ@wrbska7w4GN!>l%raT1QA z)?&DO(QLZ4SB1B9Y-z2Itcqb4Y8*tE-D99i$fB5*c=)pnRfQVi&EYy%?`dhSZN#r& zPGNCjN2IXWAfh>v1nY(>ASb!z3NASklQ`>0oo9r?q8EiiwH+81oWChhU)u_@v8GWc+~(%t zd^$d+aPjk+hw>@-4}f{-bq7m=hH<{k>{sgx8h=o&i|h~BfYbz5g;%Z- zwD~T)dtIZ{h1b5IK+uJUqn)GDh0k!XhOyR#ALhcZci}T#_$C(~4eK23F8l}wYZ#kd z_$(KGn+xy0zrNdr=bDK=cDe8?G!p59F1-8x`VkjC$Ho7I3(s{Mee84LM{6X~{Vu$F ziQ}LPf3A!FunRxdg+J=Tk8|OVx$vrs3+izfUJVI>?{VSByY%$A@ah&?P(O0vC%E{H zfGr@76`2#DVFe^a{6vWo=j?zjQsO6xoIH&U*djyxWRa66J79|p@l!-jp7H{=$PhnO zd`~Mn*+8;i7ys8dD<4RMTU6y zqukvt{2aj{PrF?Bxi0*JF1)@zko<@Xe=!m2cp_kn9Lt?Aa`Ln^632p<&id4xGt_U;q#D8if~dmj;S24PN(y}JbLBg`qWcbkC!mIs*T_qGf83}K7# zdI7&jcqrjY0snz;2H{cxzfG7^U~jR2Unk6|uh$mvYlJ!F^=1qBCBmHQdJO?TOPEt! zZ{H_CO#MD#PHnx%1^gYtoYH!a3ivU?qX-`q@K*_Qs_NY*;Cl&kit2qtz+WKDsi}9D zfbS&CDXDjxfNv(usi?PIz)`}Sf_m2rcmrWhJ-w9zt|fdP;Zgx#Lzq)dZ?S-@2y=?* zwFP`7VNNZ**#cffm{UrxA>d01^Ag+J_Yc;84q=<{aRJXD%qgY!sDLLCo<#VdfX^e$ zDWrFwfJYJL)Y1EhfHMel%IMuCU>{*l6}{U8{I}_VrxR`$@EO8+gx3rBJ;M2fD+T-q z!ZQe$3ixfpycOsz7VztYIVJSk0)CA!r-I&W0l!3;Q$VjF;AaVQ==b)0EZUzihkWmG z0e^=uhkEZ(0Y65VL%jE(fWJzZw;a9u1pMq&+i2L;KlL?{2D=w@f+5(Q&SZ5k|D#~% ziQx8+Mr<67;dvK$I6Q}5-+#Oz>%t|5asA62g$;#S7w&*c4B74lk(B?0@-Kek z4|etiU+lReXucZ!`6sclQ1&^cEK@3z@?L%07X0Tl+c4tOgWDHOhX73KJQ2$bb}e`t z_?|L&peKma^{=KM1;RW#(4HSng3;TrFyg~{ZvdyX8|5FFA}iBNmHkJr7vqz8%thJ3 z&f7i$Pd9Y3!mRuq%y+GZL*9CUvg2UP&dM*_mX*JJS62S&N3!y--@GtscNVko z?wy>g0L>RrH@Smd_Y1?ica{Qro^POnoriiZ6QuMQRd;uj)OEkC$4@(d*?;t;xhvQu zET|7&BrU>Zz6NZLuWaGl&Ujzv>Qlk(xAhsZ`t7%!GPd3T;3FeGG}u+v_o`u>T!{?Y zV6!dLAo@(%M-^ScY?+qgdQtXKS9Vv~sbF0n@_ko-uJh-??$KK?nZeTisH4#%OxylS zHtZT`K(KRlPq1_Oak%P9)frHF`Xk6E8f*J0$6&$Vm43I2_tsD6MFl$3gW!3d*1RB0 zx`ZC=OrJq5uo~GSnT0LsvzW!TaDx%x624K?qOB+n8R>@Il=^Y;t9ruB@+ z7{+BXyEFZ7lOfr?;MXAaG+?GcMGg^#Hv8q@`ulbDyV9Rh*gM#E=`RBU%R6MbUUug@ zPF0G=e(tca^yz~lxqm+rS2rvBX!gOLRzZ3RO)h!gVsXcy3w`MrX^>ltIm!MF|cFQ@tc%t}cL^=*b^@Aq*@*SPMIU*Lj9(%%2<@5k_@~b-|VB=E8<9qw`f% z^Igb{>ks$};G>_@NZ7dG*)O0R#|-+wa8g?JGNbnuVd6Txyg${B}plI5U}%_Sq< z^dyD4OWuan1iO`v=PTLqfw&dz#Iza&-KF((jVVQ{p`ZSaTOeunB|-#!w5)G~p~scm zG2JDvgPB@yAS=9*&}?I}>cPa+V`S}EDY{2lPmm5mZy1SUz75HqL-0iJ95)rZq8~t4 z7q}0V^6rphosu?PJ>CJpcpA4giqUp4j&(DRrFH8Q8ppaAv&ne7(uf9K-P1Ly^L6%& z&R_QYS}X4=EhgV(imy1>S@zM%X)Y;DwWE~K<5CD1_5?JHn3&&im|@GC?>k2GvZ8Az z%Fwk#8Haivk}XI#@TwyjfnNm$&ZN8wJr`Akr&BrUh?voYH*Kov`6ue_WUFG@th8N% zqFv^~s-7Y=XYY1hXxG|2&E<5b0-@z?^thQ2puJtXVr;7J(U%h4T~ey3UrSKgKJgLg z0<&4vE9lrK&zJfgYfvRIA)ZUA?XQfz)|p_7g;L7CBxE%fKC%>pXw|O!McLgYkK$1Rs^n1FiXPT;3A>r2 zPC8f5g6zHVsi^ducp~ZfnP^){gEdDm#R)yV>wRo!N62ya^TMVVK@yV=3h6HSJ~Rb8 zf7UbVEQ(FY!1vFS(p~b3U^vt>F^K^k^H9$OZyj-uph{&UXajUReCbSoKc|3-?&0_0 zi3``(=R^_1?*b&Qt@1Jr>y4f}shcyT+ZCKI<#hqGt#ZXzp`+&&F*YR)hCPoKm9AL* zsaJ(wdeD7UsE0DwRpEb9?ICfEgiQ&bipG?^hm+mUVZUs_3OZ@9ivllIsV)j%hB)0> zL}7VR5LY(L7v-q1$U7H>xAAQ1x+u()6&E~EvB%X&0H49FfH3T2rQwdabU$jJB#m(G}7+2^6UqGR>a4%ZW5nIknOQyK%#XaVkKG&ti7L!S5{J3XWshK=0 zF;{aKXYKezI9E*2oZ7Q?{F#VDWqraDF)7jIWyk5;?gce?ewY6K&0mzig{-;)ukK6b z=>iC{9{)-);c46e!p)aLcVDnel+h!n-Ji>A@ORNRE_eS}_?LH$hkA08k%9@V0ng~~{A&7SB0 z(3DP1-6a>XcLIF(&x2VnbX*|B!1FqIAYv$yAGk$2Z~J)rZ66QWRM%DZaj-jgr|5Ov z>20WxnfGZ&e+nVE^q@0po|%sb4CL*~!SWFvE$ z8P@j$WYncdKHcj>vGF&#G-Wgo4QT01;59ZgQ zpwby9D-!glNPi_k$5=K_&Pvc9B>kHSI%o5fnXvg2)TZZr*xa@HW3czg-uVG;b`sr2 zc68XzKs8aHU!2cH=-cYT`qx=t{%M zjZr5q!sp0omG@c_$NRqc`#+*LSmqliUBg%SoNX*ze!OQ5yo2`a>srlb??X$^RW1D! zh+%jhQ|RD1QrowH-hSJ0GtTnBKl(EAcb8nQ#CC#yauGOu4#ynHQKC5N$YF!SAIJC? zI;KgE9K{h3MVIwGE2_|4GF;*FX)Gk1&bb*q%zdShk2l?;AL2b?cgb&YyG;+=!A|Rz zD@`Fc5q^ibZSI$ZyC+1@pOJy z**l%Q6MnU%+$aY3NyQQQegXW6PH9x#)@V1lVm|plbrGn;yXPFc3(34PRV|&oBb9Sds;I44U&Di zo4vxtZY8r{B-tmp*)I_6tY+{**5zw##m=2;iP-)e6C*ykYbO~*2mAmX(A8rnpgZ(_ zm455GU&!d1m+Y54Usm~te}XziLLnBx&YfcY(-GLJhROjFyX4}i77-nM&bvuUUMASN zvx$~=-7gcd4hetXs&qXpbS2;B9Dtmsk78W(AN|z(jsJ;Kdj1`f=q;!$-(9I!RhygZ z7Zh)vy4GeGO=V5239Hr}(`^~w6s?Jp*lx=JCYdKAW1s|N)J0kg>uTB}ZOsV&Dh#x@ zGlHg2hQ~qNV9QCyOoS(TijIB))=;%+crjS4AGi+>@ErR4OwWoGK zI3K*4K}pA=Tco6j-IAVh%9j3v@2AIX83QNUknwdkg34@qOvI`QMz#~erot^P%^M1v z>%%pLjV+PdnijTZ;RZMcQD9MH$)b1%8<0U+MvDk;lEoOZ9E3eNdhOb9T@5^k$`mY= z9fZwChZ;pFuE^;YMJ%KU9jRrrm!cZ6DA8eLL6O=R`;7Dl`w?p+y@vK{hzOt2G`D|c zQ0E}dMPF)e*mCKmjRg#BERcbXvSJB&hR%t~>Bgbe1*&3fV0UwgT81}<+hPR>7i>e+ zmjvosA{{QExegu8KuljjOq1+Z>oG|-)c+%gG-;4OYhTj|b{RY1i_@TcuFm06xBfM00Z>M=7`>FjP-dt~} z>Zpp;wWun@Yv~R{$7~kVH+QtRAZ$&9leX4GZ!}_&#>SR#fiN;!Q{NmhHa2%OGqP4# zZ`35!ncdXo6a!&+aHbt;utf)+T5mVibg*kX#&6~x&Ij!G~G#yv)Cy=g0dKl@qk@g@Rg&Q-AxAVB4Dn_~F<$d;~s=7R9v|0LRyLR??~H`eg*wx7t$Xg-G}s7NRJ}@7-=8U z$yg%E#w93%lz-pRfk(hfq-T+~BOQmw+g(T(Bi)Cz4e3#&-$dGn^vhU8$;MTBAJSr^ zJakNvd2^LvZq7E(&pgN41z$}8jW5%W{Z7`=7?Hhn#MmpdhHbL88CRTl*^G;(Orkt_ zmf)BDN9ZIXFe3Xd-{RpzZiFI$q}StTe+qpE=*6ImCp0bZ`>Rku`ETNvi8j3hsiWU_ zt3!VU=vL5EmH!Utw}C#(E#H{1FAeqW1pOOsy6@|b{wbhmq7O}W({D(~vma)G-he*h z*ypeDkwerU^wsEFSGwhWWsd$Gpx+MqHA(c<4*i>;{|NMEqzV1?CK;vx^$PGl++dw{ z%a?8U``!^Mh!u960^ecqiI{%vXaBW+a?#FA*l(e4i@!~9=vRqyNS_7zd@NYpM1`8} zYjNzX0KF4*5x1!6*GL;E-vavGpigqkU!S1g1Ns+0zr;1_%6DbU{reT$p!lLd(SV~k#e1&j71y6niJ{-AFM{p(5euZRLjuK?Y|oM5}@ z*Cxtu`3(9!iayyb@9Jkyf}RHbobw$2*CzD;1oUB`SGeiEWsZHPK))Dt@wXegef<4S z`(~ygoE3A_wj}vm9Qj$G-vatHH@zlNeg)`vfIh=b4=3pS8=)@HXS(SP3Hm*tKLEOj zSJn32l%PKe`jeoGzmd^&|7pkmpMZWl=E`wy{nZKiQ=o4KeUh85`X5pMUmYq4^Wb^O zwc-@QqXE|g9va@{fj{qozvh7%GtC398N~5Z1!I+29QyBTvED8Y{r6v@ZGh2n)H+s_ z*9somTpdr%am7Q^vC4+04#Yhx!&R|H5Q}v@)Md@shq2B>p^eju5sRPV7^_kY33-&- zB2{9>ar6})`ud26dvWO4*~55W%R}QW1#3GG3aWv>G?s@h4@*SC{$tq^j|V^j>vq8K z6!1Jn#~Wb*J9a94|F0AMck|wI-&H}zAF6bSa?lu+PE+YTl`d838kIJvbfZe|Qt1OK zeO#r_sPt8pzNON4Rr;YyhbTvnQRy_5&Qs}9m99}~gGx85^e&Y?pwh=x`ix3nRq0zQ zeOIL)s&t6z;A2!eO{Mcxx>TiWRNA1@jVirMr4Oj|ag{!!(pOdbmP+4M>4z#Eq6W|y zmF^GNqREymUVN#Yx4Jgo7K_^@g>wsw3+BZIG<)mpd4qjipIY;R|{4ue3B8_WC)23+P(F&wv{YY!&qv(9-O3Xt4~LE`hB^E8U` zr=|0ch|(5;l5Sl~x;f-VXi2MPKJA?E3Y1j~6e!#}!RJfgjzWD_`jseYh?Q;$Rx7;> zAhbUUiE|oZjW5q?V^aGS>c~!e5M$RWL(TjJ>w&TEhZg^$0%jjVHm#6)ti51Jn@xMH z^C6u!=M84tp*wAEBeP$mbr-Kk)|Zxck_A|4U!&>=DY<+*2Opbm zOt};J%s;W@66mp}-V1o>Tx7>u(_cnD1CoZ7KO9*jqZDUr2GLeV9q}`n&xXp+6W4&# z(D`rToEgR`-I^=Tn{c*x`yY9{Kqhm(haX zz7I@k#?372cg!zA<%dJss)ErY*0776OMFh+dYrTN@ZK>u9auAWG|oQ5S_6Bs9{vGk zLMSTxz#otudIPd!vp>jzVo{Uqzsj1h)a<|g3%P|g*?*@s>`%W0Zme+m$ba!)0l6_2 zbljf%4d9L3Z=%1Nxg$|uAGm1C$T$4!z?FLyC`PV@dYhVZ(%(f2pUI8fde~>?R#7td z=O`;J_Zr}>+@C`){_J=)B5&th^k?KVM&pz-kF_u|-i75k7yIc0)QqaFBBJuS-9=_0vgy`YWYeu5%8~LnOXvy7f&H^I41$jGnhgl6^)Q6}*?p>xRWfV)v?GywS!#`P1w``m( zKFyDAy%FckpAp^!AB}$S7G#HRMAjbtl}C`zptjKuB}^Xub)u)*omx4D!cF#Acn3)cD{Lj z2tDk4tX~`EcusIe24@ZPf}Ir1cm-yf6NZ94JL4!Y=7nS*n{ga1WZKsNZ)ffU5fW(Ks?MnV^Q9OVzj4OL?8Kg-?MST653EiQUC638!xmoY4Syn2>8K` z6KmrQhB=Rd{@wdF8pEqW$OklOE;9XoWBlb*x8NRicY6o0Jj^}qV7g#aGic1A3Kw8O z63|XieY@9B*bS_?fM)o1Uk8V<)zi+>E4*PhgTpVN9y&`N=ANH}W5Qh&3$i;yRD?{{yz0o zc{fWi_ta3&eP|4`ik*99mYYmF&G=(p>=ny$Hq~3+eH+X@|DhGVr4$*{rqkM! z1ijlun0u}VZ9*wX=1E#iUrtC9{2bW+-3O&FPg9z{oG!-9NK-pAPdIb5DZP1glac=n zy*tbF?x11rc>-!@u!^%xW!g+p@GMjMs#5AI7P{!H{J*k|mzmy8L(Dx4M-i%)DOF8U z)iR}Oy)i2fwJ|?u{tn4g%;OLXUP#S7V{pGRlPGZLM$P{UyWbkqyJd&DXEC@%X=`+8 z#;jhNcCE>&<&08)2^Hcn_w1nhE$F!5;9QC3%!{$%uQTPqYclfN*?#Ly?}jDjo~Lwa z>z&f_zYHa2gX!H>#oY6ImXyYl8dOP5MnMBr-z02%EMMBRMJBLqBp&@|Ud|T2$y@}i zZ+DAPxRn}qn&;1uZ0!zr3%Ny2cIui);hjpjI!{~%I<*_8^CgJ+C9_iZnk^XR1egyp{7l`~g@8DJ@V?b{uk`5L`&pUJD0Z}*ZsKHZpKPE>-6 z59YVb{F$-{TPCP-8df)CCBEf2sc;vo{B5&*0QVe+``Zcb)9loH&1S_t+0h+wxc6#q zY3E*LCtUC~4zH)odzA2WNB97Rc^3ex>?ch#+t~{>xPC@^q=TTW^L0kiqpal9g4?@? zjJYRcgzBhI>#j3HG{@7*N%b>DFML`#c&$FJ^aW+t(A3I2(Q#f-Ra-yx<^oys?aBdpXivj@Lw6ngg=-_*|F=TGyEBiur`It@ zayaJvR+}RW{GBQggKRmy)nj^hy)pMp%hFZr(cH3!Xb`hch&|*z)4TPNxu=f8qHgaw z!osodDMvu~Zq5&(C4G1MKf-Oz)mR<{n?R zHsFlXv36!Nd*~Tw=&&Tan|}z6{@wp$>&!2+h8o_tHLr;!eq!>G(!cxo*1TPWhx&FR!Bu5z-gT^Gj*o*G zm*}l|50HMYf{$%AW=&%a&iB!@>9cXdp;k*Uh7Z#uqQK$I*d>&(ecsKH%sn51dj_}v z0af0jG#U0*8ZerVv_t)e1Gd4#{u668hBq}s{YL{faX{i^o=d@@{$l|f5RiPtGRI2f z@qkSnkZhuH?;|_Z-xIKr;xI>=Q%B?s^N%=x#7J}0IoVkA@=Y;@4O<8lDzCDzCT*Hg zo`c)_ED)I)!VK03#u)w)mkzrOSxaY09-3qNM+_TAiU}}dxMC~MnGe=sqmAkCS7r{d zmm@RWG|O|yH)0}6DFR29QkG6-*^aVwGL3{X3z|WrvQbL60&~(#TBu9T%|jXE!8TfC z&{xNZ45qVlOGK5%Is!ubxY6eHaV+M%bU{8}l?I(GZG0grM&;AT(P5=yA6O)~FG!b0 zfz5}7JKTjyHVIzHwLE)n5^f?uRzpcl5>-bVO)fOA7&mAcQwj}DamvOX0>jXVqtLyk zxdqE}92Qn)x+)A#qIr4B6b0rxlIfmm%}~`+j5AfW6gW#c15%#y3I9o0e!uZ?bZr3^9)3ZM=3%G0W#PgO99eB z3TTd?R;@G?qZxY;X|oB@2j~Htw@4}@Sr}yk2m?e$_{hB1J5BTs<}III1@KQX4;-+r zS}0DwwWF+w&-)5S`zGc1w^+~mGi+;zRb=?m%ptKMjq&(w|INM?W?r!sKd^hDwScFE zd#!bQ_xdi)IdEd(RVQ9sXuWd+E3?-KnXeBycHqRd*1b4AeBi|O$Ic!&ah-LD&XpDLE%j%sF9Qb0BU#Z0%V1p>Nr^g$MQ?IdJXSA0IjU9RFJnAAuhKFL|=QBvd{- zWV4|8uYb!w#V$SqwzClN73Em39XVz_ywSSzPgV}Bo@m8=({imMl=-M{ZVqfZYrXHg zV%!G@PCO=T@DKGhn$n6*)<&I-mD84nNnH>>H0b=$P!0|(X>|JW*8c))5*kQ=fz&DzC#CGj zMr&`eb?v>@I;*kK+AIFwYi;z+&+*OA_01o>mrAXNeKT^b*;f^x*lq0wXFP5dUsZet zm9QEY!euxWS*I3Shu^i<9YF_h{c^3whkcXB`X=Qk%3T) zu%B4R;s{>8812#UMni2KW`vflk$d(D?OH`uSzyW4Rpr%X#%8hgAeMkS5E>YWMh$F> z*ocTtoZ@X9bK!b~-Ng*ozJNE0n5$)<nV;1|g1CrD9D@TXRPf;^NxE zn-QPr*htfKrJ!?Fb=B&{)u?o0m%Dgf6M_h-iZQOnfA8{8RM(3A3k!sE3+ltQ@kW%s zWYOwXp~|Y2YuAOARs@!<3N2X~TCoy!TV1^}w5mE#Rjp#&3=w`P_heiaqST7O^0Ls? zf$GJvV~W0~HlYX2r@CWg6`^WLa5tsC>nmKt=fyb{861SyokD zUbaeaI;VH8(=l*x9Xm?7+9VQv33I26ic9VfgH&5sK}U<&Q*J+5j;U5|l$W$WA$hd9 zNwsjhY=ej$L};<>GNEORP(^efH%Dy7{(2$A9p7k#bUd!y<5E{k78>HD&cc@C$7$aP z$#7TNCF3L+^-CyFiy?qb^ca*Wo2GhQWf__gj!o*zx+A*!@@KbyC{WEFFMDVC$`#(N zJ!J?a2D99n)7a1&sc&v*4o5qT7Pz5B#Zh8kPxSZX8YhJ6BfR7q?H%pmI&QC+*x*ox z^NLF=_Iy;W$&u3-s^c!Eytra_(?&5;RKvR31^sO0)#yhUse#4S~^<<|tN zSsC3;(bcQV7mGeEd{%+5&~VfUC2c@yglb#j(OS2Y#SpQj1_p}DomoYz zSF#gUMnx2@Zeg*5RPgi(NG(WhL%VTW~UXa?ZvZa zdtQ9o1+B4oTX;buB8a2SbpUIkbxjL!Gg&Ziu3gY*7vRop0qOwBf`-cS#W;)IWeYGO zV;BOFC^({+2aRP;R}3xU)|bw-Et*q=?K(|VwzjgOd~ta-=cn?e>x{-YyTJxrbBv@` za&7deeXLq{QN`-2MMk5(L;Y{vY!`WNy6SM*UU+8?gpN{ClTY`O3$X6LdB?c zE{c`#k*Apu3+>D!821&}iB?=v>LYPRExRUwRqIw&mn}Dv_hC)Mrh6|_PJhC5#Z6{) zOg5&K>d5L2js`W~I6>jszZHSCAvIHrK~>2+;iWA#jUDLK6}YcP3pHSOSYF{pvt2X? zn53OcF@LCwxVXm5K?ji?n?e2T`l2g4mquku8DrUT=N&;;fPt7f9QH=`4h%-NlkDKM zpMyY8gGO_QzJxeF*0Zf1454LZqEQFku2)=cc$vXn3*)j;SyA&ua2b7R<>#t+g@ybEdQiI z{W*x(sa4)MIP=pYxj8Hpq`CmK|dWtA)R0{w(J^Ey?(7*^$XW7%uP5dBE z7X0d6crrWq$9pgm^c(6uv4`q6CU`Jd2?8d~_>0)1$W6q%8_)*&jSIFu?1!(vH>71~ zA@S{=DikXGK@WZj@Q5dI_W9SthU3p1q#bWodh|ZO0L5_^&gLNf;ak8DR<9ol{;`H$ zAI2iBI9^eBy+o|>KU4T)0UJ52*NQX#^aLsG*9*lOKMWNiUau8nRY)9@fERvKOXfooxZ|XNIy!SPEr^5f7zuN~i4c<)O>hPSa?@9V&^ z3h#aKH$&mQ@ANKL_yI34;E%!j+g0E<5eIera^*0UtP}WwiWL`>ve=`OC4+5V#;5!$8Nx{z;xxvbv z1-zXw!^s6x@L!z*e}lkh8s2wfZ7KL~Pk~SMJ)oCT@c%9a{(}_w5tu**^TU)Bc=?^F z%mINQeDR)b4E(Oj0--0<@V*=_7x;nK@s%mcy)gy;3n}n>Q{aD}!VmnLlEM7&s}%Tm zQsDoV0zVF`=Y#1l5co{P8^&>&!h7HUUYSBqO$t0?2nQ?ocBS7N8gq}rdxKcM3H)H= zg6}T}`##Q#0`CkTC&SmDLRT)X3RRS^s>X+z5?^Bq#agiv8EM1kltQ8UNJwr_5UR&2S4XHOzL|f! z-p;SD)E8b{a>?AmnZ$RV<^CR{dN{ zCGn_U&ivFj8=t;boMI(WFM5fWInE0ptRW^Ad)2Z_VtvW83^T||iC%Yg)*l8gD`*zA z$}q?~r{q=q#IjP#g><=^1ariyy0glq5w2x+h2oNX^4ged`9)ZiSO*M+mf{6iS*UEq z5`NfAbS9mz?}#X)u-dl{FILJIg9EFtp|YS73ofYws(SfitzcQj%0+>S(8{GtSK&>G zSj-7wQCu!=itlHMS6%#+RcWdFt24u7Pwe#)=}$H#eT9oi*ULcX^JmEpav$Cu;8$Dee&i*J6pKA<(QRxo^! z@}#mF`4KAl&9H?1{G3tpr?yn%>J`?3rKk@>$!}^Et8Z&1YfO6cmTHmT^U1vAC10m4 zTh(hceqYY{Qkwo)Rno%opi8};)oS_Wv}9ww-^ha(6R)w{L|B;gCTPI7^2B%L)ECg) z-;;7GqdF#bm%)g~7{TnA^dUXx!*qi*V^aNHU-C*ckW|Y>7d5ht8r}&ltt^!EeZ}OG2i7&&?R?iY;2Vl!{P2ngl6aLQze8vg;u~qPnp&i> zs7#x54qF6;3-P9{P`=g2n*{-36PhNYuzpJ$BxQ=XDT0Fetb=c$-9QL546Ygqs9ZaC zpuxsV_;OnzvW1Pqj!}m>v_;8w0$RIbq(6EYE zSLl@Y?>ty8%h2)+(d1EzA9d^U^?MDSp2mH(`%u+$P(kGQH~3m!zyHwbV~SJTulaPk z8g%|mzlQaD5}oSxR@%?9wf#!1*c(UJjX3>2MW+W9qb^^|>-x8WPWeTOPrrB3>2VTq zP@bM_%t!p;JV%CmqV24(^|jWBqme>-S7L6@TF6a3}n) zQ4e|Kcg>R&opNs>_u(!7+aS8j*YB-#n(68PUjO|7@+0um&7|LN?OPyA_40e+7r=(U zE^y@ad$9fgMfrb&EbZ6j>-S{`|BLcRA%V}QmC+8Y)rBfG4 zVEsrJ5?QbONFcm8O6=qdJskh+lc_#?c`r;MKWmMYcvg2DrNApcQ^^y*{gZRh5^j(@s{W1eP|;DEZ4?5U#QYzj+(b`EYF6Y;wWKi%*2^@H=& z_Vqij-}kS6AUpFs^UO2PJTvpmd}ih|^SR2JwI18H%#&uVvIvz-RG2ayaPW)T1Ey&m)JP*)}cS6TIq2n1h zhXis6qY4wru~FyUd`nF?(gm$ZCp--F1!EbV-(@AsqZ>hs?JkE^y$J^JgLKfAi}mDB0rs$Z{qV?*?Fb)TQ{`m*o~ zSAFl2(yLp))w_1z+`H%It!jOK%?|JNU%w@L^M@}Fe)OxCzms;?f*-k(NbsIOM#d&! z6p#zW42QoO1vDJ~t10+Q06YIM{12qyKPCk}ngU;!0{=z|c|L?J!^yur1^!G5{;br) z@p&o*eJ}<8mr~HrL`58q|Gg>jm#5(Wr4)Ktl|ueqDfpk0g3p{3eDYG{DN;-5mE8^B;Vz1@-mUzCE+yD8+%Pm!-*q~KqYg8rK+@Hq`xYDF48BQ^hL&sKCh5T8$; z=5v+ipAI@cU(xsvb-rdRv~`P=yU%)MnnL_en%M}myq6^%5u zcb34nyFL=C?}%#ITxm7dx3vYj_I5OaC>V)^BLRs^iuPbfEWn>oG}s=9*6*Sup|++- zumi+xP^-`enqzHkK!h811{6l%} zc2j+{ei%CFr85|b?hSw@9^56mCoT{{DwZkHOG6z^;XPJ6vKDT%+Jo(k)ujv45kkjS zBDgdHM4%aZV0mc8bcI?_Ap(uzjt*u~gp35+g7sZNmDa|N^(g)tls*&@YHAAx>YIkk zuagfHvDF9$5vqr3Qjqu@Rk9xZHHDA{6%-YWMQtHjha>#tSB=t(>#W_Bry~m0M-Gl+ zh9_wVhuemsks1-G@9YesfRWN1}}}wiwe08e*u$!3c6KEiW0(qT6~= zaBtV%_PX%qDB6F^Fp-(xp)3&>$+X3Se@#%Gs1@uEHo9t0Td1K0e}#*RN{YI|MI{yy zp>P6h3aXHlq*@|Wsud+rHZpXn6$nZ#3IrOuP^D=l8KJ469l_SRn(EbS0*k=J_!bqZ z7e#H3jg=MG;Is*scNYdIy!$sHnnMw%wXMJXpU0XgeWv0$E)>e<+tn(Ki%kxVqy$xf z`Iz@tuL9B0D9;P}{nX%(>G$e=<$fVBcmtohK;ilBs96hLzY9NAFzV-w3vb3A4EflF zFLKf6mH7qYyPxi&1@^n}N~40d3S4-je}(5%{CF4rF&Ey9!5I943$LrD#5&=^>#8jH zlP*GO zpPBz>2>S`268Le#Y=Q$P1b&!sKH*~m-%prLZr~w-?;*^lHgH7XI|#Fh4IC8sX2NV* z1N#L20^vD?I|aU;Fq_iA4uP*G%qBEYD{zGHJi=uH?<72*aEZVTgxQ1!`~v^9z;87l z1T0Tg-^z8Bzv}5v)2e#TR6X5)L6!Y{)k~j7^T6<8&Co}Nsrc<%`Se^rUi*uy_OG0S z2#^f&_^NtW-UEF9N|Z={6@H%2_$pwV;_Rbf?>`Hc6^i_dfo4!JB3gM)RnIjaBlXXK zoY@%Ey(JtPo0IxgC`EY_-qpWMK1aaT=ZLYbk@2w(O-+?kfPjYU(s^@tB(-M@?K-PVI4C=jA<>MzkKOa2tj(xDIS0rev zTC60BX7s-XGDlZ_(QQxcOwX3nRr{|wV?~?xUvt{J_DTRBTd|QvxYwRv! zuTZt&y3@6yt0!Jy+C7gP6X({);J8Yu^5cca`kN%VXP_}f`zllTFQGqhl1{I3fIat* zWOm>bvHPE(V?{?HoW9YIS~nbv`62OVP{#eOXt6qk{GR%s!NGxt(f1f!U+HH-#-KOB z6t$Z%dl<7QG3Eir>}JgUPf&bI()bD~U#8?Lbu!vc$_*+FQbN*xI=$LKVI5EsN;{vc3Zn+VczyM;KB(#b%|-`5WYT{J;rHiN{H}7PUlV z=(T#DM>Z=FO~q&xg+A|4mgPwA-ghf`Y%2dg*_1zqW-%z0=3-w#dGy%PbZ78`3vPNQ#lR3;+A4&3Vw1)mu@fvV$WUIan!64OtGOmzSd(k2Ofyv*++%ySdwQ8GKuG0#Pq<0eD{ zKHh)w4-Q8ZicT8%gTOnjeKX1wY_I7@+W0GT1XBRW|5=(h0<~cM`>6LGv`OH4YH55- z#29r^k3moWtE{m5RiX&pT41OgMNbwkzd%`RMFh(Gn37j9>l@!fbYE$^4*gL)lsbux zLQ+>Usa;6wohgdHBMq`7rlNwe_CJ@m-7!5S%Jhiw=y`;7Gs)&WRRXd5r%=lYZS-;C z#S&832Sgk(K2(LYpq`wk${6>*80KK1Bd;cqD${$bq}^Bg6O0zYO4a@CNUwjkBx=|x zrV*NMGsih2VJqh6DmM-sAoAlk|8*PLutB?;efwCpb8C@*rf_u5@j)AhqNk=gGc`^X%CJnE`$+Ls@U=u z?d3sg&}}adftkx*M#=WL^d1z?NnHw4)gGG536Niv;JH*1OsGptz6|x<$_^-%xqJ=d zB&u^NBP(+$9T==bH8_diF_$AKAqQ3}!Jn!sC^TRZaupK5)ksz7-l=s&63dNhh1M9? zW$&$2t1;)2R~aQ-ED9?99x_M???4GU(bm)G`eZnT!OJ=C4>7vh+CBl3C_*IJWC^DF zj>GEp7bAY$*7_Z5)K}W6)$`}yQ@603V$3tq*gt+}L{(o#F@#HEEfhthFxG6k10Wmk zlN0Q}HuEn7bZntBtQ8*9BpRX|Q&Ikpj&ip&qAe zxq8z*RgEVgWI8oypBOv^|9)iXot5x>o}MM}^wKjQo`dw{!*eS=li>LpJvs2)MGy0P zFFe|k?LRGw>WRGxIs2V<{_J~_zx0u+)NVQBQk>Y#o57-g84B~A*^CHX907(U+z;BG z$`6?B-t}+xZuy``2CR;LOQc|WVyCKlww&x)|MKxlG&QjAtptXJ*-h5ZKs{)lBN0kv zyi*eo4>0_mcsSap_0EEL_*#Zv9}lN7c*h6E|BT%9??)}^-SP>@`;~3~5FJyz+Bjp@ zCpk&L{JfGP936m!KQc7DCnni{lEWslxH*Bu?;e*!OHXEMvRy;T$f;*bzpAj=5ZYA7 z*a+1s}?P^V;bC$8F{8WEBw1b9lrgsaA{R~R)4Gb$7?QulI z%hySbUW%y>qQ4CE{%cOzF{TIl@dKpqEB&pG)`jqQR)fOhP@GZ}zt$8Nlfn;*wAf_L z<7Gwhw5BMQq$|%nE?MX+J*x4?S^1EvQ#oe?;WjjC+}Jn%P8qwF_8NZ4@qUK{hKn~H zdPiQi>3AP$Ih^z!O%d-!m0q!q_Y~vpzos99J2PZ)SWrJm;=8C3RAA#|GQsA#k0+k<|vN=an&o_CF=E^I3JpHG2 z3@3fnvhX^p1w|G_(5)a$Zhvm7zS4iuuf(H} z1f+enX7roW(BJ_^*ni4K4-8|hNycAB64W$BsruiWT;!fa^2LgLo|}A|i#$D%+^5L@ zq$-)>KF>w&O(g#n>H124>?Z%yJCvQ-G$YD$S&p|?^&Hp=B;HTySg{$Jh_&`EFmTn{ z>!JFAJE*(fTP2RkeQAR`r9()`Cw7qKLMhB|8GnKIn z=6L^uiV0_SK&~8_BY~8&HLtzGEAe&jpAavpo}z6Gp7@Jnj()|GQ+bM{ahpU%WepU2irTNdl&dS!qHZc`J-WfQ`oW^!|g?l^&R1k5H>*+ zm3MZoM>0j5WWxx=u!iy(LNkOXB?yFNXUInG#aPo?-_a8EhdOqLcLkgLdqUAxe+TwU z_+!YQTHODu^dh|<8z`zfn#0x}+1#+gPn}r>vG80=NgRymZ4cHKSvF@bBf&zmCjv=x zQ^W$lZ1Py)pVehWBYPE*Y-CVMa*{zlpqn{SzuL(mWyO6Uer%2KQ!}#TLKIFtVgo_2 ztu3^(DAW|JFKTHEH`KSW)QWaO0oV@_u_{)_x~O1oPq5l#nO|a?bg%)y;p=Y*Hr7K! z5V~-cst7DbD$XiKa>Y)u6*G}yRG7Bzj5ar$WtpSFC6$6A!*f67^hHxxe7!4P8wPG6!!|A~$BKTy}L?N~rfHu~#s{?qyF!#%jAsa6!XW=gw ze|+DWg});FEyEw`CAU~?mdz|HR5f&p2l@Srj{F z)YaLB4H&X*sl7h3%Zi3uTH1nzB4MPyDHOJLhq^-Ci6x?2^$8hfHFIgi!iExP(jRX2 zO9h`Z8FxHa7Q$Ptt{njQEPJy zyNZ(cdZ1=RW04M3-K4tj+!fs07;Xx#oQ3i++exryKPBxv?lqqQ-5q>$aIg&i&fg3U za)s@({=vb0aK8Ze2;9fv9)tVnz~JC1xXWM~xoP5hxPG{|!!3jRDS9NCUO>mP5AZDX z7f0acVkq$(+%CL&yb1Saxak;#e-|$I_r43a0`5W#;G5t!!My?Q>u|pTcRgN4o`d@i z+&AH7p+2NzPox0T%{;@Hx1<;Jyj>R=DZtG>*ZY z3HJ|hE8xD1mr;(pGV!{516)34P29eElVx}3*i(EXya%C!nF!r+MCt%fR}%j`a@pA}+)BG$RA+?dMVdWUb%Gcv(C?>+_8Wm%=jPSH#0D=vxa?Cl;c4$V@|Pj}I@qI0 zZvJ)g_&X4OHNx}V;ky12_4nuR8u+^g{;q+)YvAu1_`3%Fu7UsGG?1q_n|J-|*6ts)o2fUY zPtfjc?Jm{sTJ2t<-Dd6X*6xkky-mCKYWGp?KCj(ZwfnYq|DfGWz4?8Dc4upMsdm?D z_Y&+Pzo1k81aM?Y^qrx3&8R?Plr9` z{$)jri%JR?EsF`b@Y;pTi%OQvRcP7Wt!lBVi)ZPo{uAyg9_D!nO;A;KuYDTT(Dymi z*_CJ~!$tI5jdtWYxg31byd$a+FU>Qe33WL=J%itCWvoR=rnd>d8JkFCXU;)Q&bWg9 z^bs2v!JBarB!jb-j_o}g1fcWN@nkGU%APUcnD#}!8+*8?F0GH=5#CI%@bQkQ03Xk# z5GB3fS%i3>0{xHS8TlH1_;(g1#EjA`*rU7*YZCJng>A^NLd5&_1F!t)zVTp|VSN*5 zuWujhmGb9Uo-3I^<74C#0?ovsWUw znPcrQBcwZfCqpLK7Xa9o{b$sH%!&2^0M}<9!Ea`s-4Aa2vyV`msrJVJZptnvgIP8w zDGp{|&NziO6?uDhBY`3Tj%4p7P%OZG*;f%L5#XWhZUT$!Ld1D2`y(o6vB-8T`)-O; zYJZA!p0h^XN)hhJDnR0SnMasO-+WTvO|RuEN8QQ1huQV|Zl_l6Wo~nzkOzRv^m0aY zBhMA5#sQ5uaz8V|Zx6 zh?~UwCK4IZqr509?_>%xaw~p1Ks46MXoNE+583ukAto&+eH;2H&m`2~kp)zK#sQ!` zk1$$c2)~|8@EN&;725MNO1zrhk*qe)gHq(Stuf1?g0t>=l-&Oe&75_F36EJ%in}}M zT|t6-g%UP+iti5j4oS%P4*Zzp&5cPg;8V)zDd*H~mWH_*s-m*7|QU;%xG`v=20y z-Y?^K+}H3keh+?t$c2+Z#Ds~6o%KKVBk)h00Dn%_pKOj>vKNrmpY1&Ot?UbsxvWnG z@FF_1lIbNc&pL?in|Uj8?CC=E?74%$W<|&;dp=u<@3Y83cHsc|_>KdSUBry0`z9lS z>|&-xmP-+m=XnoAql#CJ8H#s@K5QqMy({} zl#n%Q)o*~YJlvN%YUvl@&-xVJoKaN|!ao(17l{t0g0zODUdyu$(vMp97-_e{>mPL~ z14w(B(E2tY3!}DQPf>jhP{pXrKLSCHHIhX@udXm7Nj?Gu24)?dXy7s{gJC&0qZ~({ zZ4;mKW%|z%zvlt+oJm!Wz8_xC7f_;O7H_S;}RCSd;#A$i%{AULL8;`p;~VVnkuQ=n8#UgIA?-l2D< zA$liI(YpybWuUgKErB;L_ovsu zKb4={=f2DWwtT0V%~$C6PUUCjxv$O#CHmNn%+P^8&}T4G)&{^Oxo>iFlkcCH=-Zco z(DF6GMCA7Gg5T?VkIV+XKnA|gF#hQ~;m`Bkzzm*YRKM@D_|5(OLf{K5&-WPln`03z z(_4;!Oz%zddxc=GkzcBP+$_+mYD5)`7x352K&F>$Grd_L@SJ4&Z_r>!9jRp`p{EZ- zRDGuRd;k(op(Pwh_K||5^ePe=t16c1W#2fCnKASS;m=t~efN5(pPXyKJNJvq|03&F zpYrb^%|9srYt+d>BPDAYM>_WhJWA0dG>Yy(_+@dB{sJfTGrY7 zCKlN=4cR+T`z99K(rmLc(a}sSkpSose+K1s}uj^?j4%W!dcgd}YYPlyc(pd?9jNO~2pwj}T|d znzKPu;G0bPiemU-J`g&klK$mB?pmF)wi5m_-}gvUwG;j-AGhyJxrj8izEa|A4#2S$_xoJA4l^?uLipZ}r^@Q#GabP53)~m!d*V*~%8y?F%yQHkyuozDHoHrd&q+ zO}>$obNe4bf6%vpJg*?l?Y>^heC0S`j#x8(1wk{t?3FXU)W$gGYdo<)ybDJfBb8u~ zp8`1}4~R@J+X2QO@Q-6Q#uE#~Od^>W7s^1q`5}gVUpo zLuDx}!-4%R5F#|yr9!07$@Fq!XH1Mm((nRk$2`WG)5rv79D#zz>_Hoz5-bB%rndyY zIX@*qjyP&qyezteus%;ovs zf>hH^((m_;W!ztKJXzqoiz&TEe~Iq~NIUKI=g=yaOZPtQKiOTE`CcNQ|DwMFx%UI| ztN?KKC2R_rUNY78;+(_3LTLUMfU)y$BBAB^6uCU-uHyv8GV@12f;WpN(dGF+EI?C} zy!by-dEv0a|Hme<_li9JKT#f9=hKLm^C8N4`j^t5hJUsyf&6c$)q}~bcaf3L<)_1I z<=+b`JO2-m&STA1mMs5F+ARpn?_=Z3zYITi{>@0mlYa+zrRU!Pk-hoFOv8!tZ|RRP ziY)Ty`yqy%e-|?2u_ojqff)s!rxBbr7JmQC#c#v!`yGO3E~TUxbfDB{E?a_674xi| zDM)r!zUMshi@|F2dGNvr zz?5+gu zuqqRV7vtCSbBIvTei+`-ufpqjobc`60-W`Ic>M)meF=UaxfR?Q&uYQfh$gQ?a6PX; z?zvOmfH%|IkKb`0<7Yf`BR`gB8U&a-H4W23nck839XAO-ieM9{EYD)7Z0L2F`8_P^a+lMFN1N-@BQ}`d- zw1A9J@O2cX{cZc+0!3|(EVBQh|5+8T;D@eV zu$bKb+2$B3?a--f7d!}s*^kTYP1>Ost}T2M#R-`7Uj_dnYk`-_c}~VYX@^c+yWlQT zyrAKe*IES;YW3@O@|kD$;qjPFRRVrp1oRx*IzJZ)gLo78dk)pkFJkgvm*hN$Y8FgE zO}4*bpDTH9vkHERvbXQDlaH;l4{vf<-=$f%&i@7FxXWgc=TH+S^E_ve`GWP-$enib zQFiuWP7W*a?sRzEfMN%+5^o2p1LgawoqXP!efVdL%({+yLPVhQJ%{QRNZI~_VQ&?$%LKo6fv=hc8a%SG1+IPgVTYfh zaQL+we)A=B?K*Q+^Em(pJC$0kO083;wxi_qY)Qb{uN-RuUoq_)oO)>$k7nUCON3ck zoElARAGR@*JaG0Z5ZCt4%H(3jRLHIKJ zsE+J+B0uRwzRX0n7Otc&F0t<%LVenyz9ddPnzgFZ{ zYwFW%3CTx2+J`Sh2T=M2jJfQmSw1ksdrIG=(S4ddQre+odzP{xJ;&H-hfeNU+7N5D z?B6gNO!%HT(GW2IkY(adLzv_oIqUHT3@_Iz4}v_t!L7tN_-1uo_iQ`({1cdI(GNag*Z z-PVd2&Bp8%nstf8x)-d^ZSQJ9pt3Nn*7;MJ#p!0@El#WGrW-o8&RL^!v(iRQ88yZp zJ0b^d-ZQ~U8?_?qysT;r9@1u7Sy`(Pj($peF}BH=Z7~qWAxo%6(1Vd0V=`c*ZCB^o z@SHUrg#5%dE7wjNm6b)d#QUwDDlxn%5Q8HPod1`Q(R6>}#uHx#7%5r`J z)E>j(oqLNr>ha-Bu(&4F5$j$jUmfuqBda*p6)DDNV#O_ujm6!|mj;$DDQqK6VGBMN zT2>tDXl#o$1r?nJhSD{JqFo6jalS)%no~Q6XYGX2lfbe#A*i@1*crjMPy7-{@?d0( zQ>kM(8sSN-%i?RZ`KGLGl=kqAlXkn;h6>Tl}hQbb!c+qim?d{^p!aOfng)uMqGN(C2 zCa40@PE~TWOUsc5-OpK6|F#@W{-Eq1)gOW5uLtzwLI}^s>2$0bs zAr>>v$L-#$LXl;Z9{kjG5Jyr+ai+1PiE`yfT>QWa!RTexS9i*vTsvA>JJ5%DOz)ZI zw~rq6UbISnJX^_QqnRzS*uu1{Jsa$Tk{>+i z-FEb?RTsUz%KPS9-VeN&3CY(oPab`1yZ2`N+;#M=D^9+D^sURiFM8j8(9=5csAp#G zTW>9T%X`_;nD;L44Xchm_~Oy+@BiS%_n%Pz(^_9mo8&Kf5zzYx@f7EJfAr!>?_ImS z*Z;Fn`N_beMnp<Xb~M#<6L-p6K?#ys=J-K?HiNk1fy z9bM?%_WnX|DCTWBB>!)I!kY_z>hCSM-eURD%wF8>eXzv4{buhrZ%d2!LHU2PceiJG zu4nl;&+_pPlBxGD&%9jk!i!4YI^;bB%2>=>a#6{9-pk(iwyZ*)@l)(Qy~_K-+um(2 zqDWkS<(ZM^$sdP!+n}9o-lI@$i{#Uj27BBUjzt=SIMEs(sm3BT_>2$V%eBX% z!EQN8d|jYo^_Iox~AY}`<3?Q9P>g_=WX0#;yM9a_+uw)(Cvb0D)i z;#o(n-L!G*HXXNOBcj&@YBrWv1c0xt+*DUxxfuszOT)mi=WT5bID#Fgw{OHj>o^fT zY6awTJiaQh0S0iCI>K9G*dDcbk+m*RTfV7$eV}q{ZB6x>>N;|-Uc1fODIXm=?9d`$ zUMzgq+Fl>E*42r5S&Oy};qkE`vX1nSM1Utg2i9$rW6sf9y1MFHf)-X@(T1>9%!=;D zN#u=|K3p1<{Nfe;R`=f8hAjaE0C?-EU}Yd2M2QeIaHBNOJwxe*+T-&Ws(wAh;2)@kqA-i>s) zs>Z)&;X<{w&0p9ajdcW9w&3g4NT?BDeWbBotzLs) zIUv6f<|c}sIvfE-B#e);RTZe#r`Pjq=W3+7h9}9F%V(@oUREICKy_${B2^xj?^HajwDWt@)i{8> zYmHP0lp}gJyb+mF7WnFL2a;cBw7#<~OciaGhGvj0I7L6y&1~}6c~wVDuFx$)3!DW) zYE9A%Q51ad>gE^7QkS~wcdM!-n%U$&sorT7n<~pIF5Og(8Y15;s|yFz=eSbS8gK_f zWN(0VTnY$7M%5=+IMqGU+!o%0bJkn%7p#{r@^JyePMn&rJ3edO8q-{3H! z&1M|VUf#yZF|0?d6Al_tsLMHB9u*3eJfidf{nS-aH!wlf8=;?VFdLiJ zm)GFyXLgt>uhOEL>tPzHA1MgAHUT$Bv;{lDPGx2rV{MN&czqH(T23PlikDjyoFYN3 ztE*lU*igOZB7Ez8b&v*b-6iVg1~D7Zaby?GDz2Nrl?*M7xPT!9v(&a1gcZCxVMyz? z%*V^aWUOZ6rBYouo>E!~tmY~I?uJmgd2{u~4aVm1t^kx<7`AG!#j4BxKtBAopu=v+ zi*i(!tTT$Xv6}{~k@o^Pnn*hEzBz`Et%JHxQP);<2ExtFNXgh@v5nq`aoO0$N8Fk+0oWCr4IR038@w63%DX+ZJkR zWiiw_-GW$TRpzRJVnm#9xd$0x1TRf9t`Dho=(k!p4?(nOU9_aE{Z80v-I78bu9kF_ zR2g+Z!B+IdIJSXt#bg=7q4kF#c8p3m8lNV#9auq=W48D5)o5kf-c-ce+xM=ok94)d zrl^ZM`0+lQn-d4kYIEJDEofL9H`HunJu}^!6+gp*`B8NfRa3fRvG#1`B{A>UtJvNEvfu06CQC8mdlIug?0Wh00l^oW;snqMTCefAWTDB$9faDu4~>=x5$S|jvME9rD{wdhfY8vq8%x72M^ zJ*Y0ESceo77@)_n@TaQ;%Ackgy zg>lSfs*}@m3CT&XuGz9_wXV%^OUBn9UU;NN;Q=#NYvENu!TJvL7$D(jGQ-J@3~yhEZ@^QBe#cy`U)7pn)^%}oLQmaE6ve38T`wgE@=SaOw*8XC7q zCIc)`jLT$5yl`pKEnve4rC(~}HZf3M$E>J6mE#V1g-skAn@);yvKvQkP3|{eT3%ZV zv;DUug<_!jKzC_cD2uqhUA@oCYgl;$tOIU2;z2`b-R|3)c;pd}M{@P9y19ua(3~*v z;z>Eyx(etl65hK(&O)*uG_mcr5{93RIz(8V{Q|3uT`OS%jlT=k3-Re#~ZB!_bkt(y$n zJ)Q3!6Y*)5`Q9-RpYD7YnTXG@%=d+f_)N=umzanjVVUn66Y*Zldw9aB92g+HEjrzldtL4@A)Z9!h_uz zsI^1O5i65|?@TK9=^AgoS2oO+!DCx-J;-D)aBBrWv|QSOXS&HM+AH)!%lCHRhm-$) zp`U0SEce5Q#Zvj@y~s+Q+spleG5BWyFjX-cNy_fW@NW=oh8HSEs;p zlgV&=x>MlIeYeS*i@pl_oMFoMi16`Q$=e9OCHSHJ+QTW*{YeV^yD9KFSX~<~UyD=F z7pI_Kkpj<)U54WyPJ!Pqc%PNL$?TBECvQAGl7i3oQsAFXfqzBwPu_0E?M%bf^G`H= z@}8u#utq#weisVfXC?2;T&eNNd%?I}i}xQV?{lqB!9SJ)e?ap|-tO9k^5s3yN6Hg( zcXJ9p_h>%Jdy2oU@yVOEo&bKhd!}DZ!T~JeVv*gPw_-^ApdU`3 z6@njnU-*U;^q8%VVi!SkGqzt~Nm5^29f-DLo*Rosn1l*6g#+qr-9Qso*t!Dsv2M)K zU|thf=r$ECTY4@odmWBQuEbXN;$qqca~)PQ-UBf;$_ZdZaX~UCnm{^q8Zlw@%(XJC zm&DWyyffF0c{$fY&(QfPv-0OG5g3G?=O1PfE9u?RnU5PfyOp?Pmpmh-L)~w|!%X)K zS+Pu7a0~?2Vx74%P`ROk*N+F9y24rz%tLP5P`#7R?osvNHEgy-DjS{~xa;=7h*!x-s36M6D9E zs9VDI9GbKCJmgmJCcW02>KgH(;ha{Go4%Q4&J_%~8Qpc!xpO^xqDmaDYQZvoLHJPR za5~q?8?vLcY}%ev0c8osy^5vpm`}PCJ}$o7^kN}ai^TiuHu7n#>SCr+p*O_2^wMPHze$sf69Ub%@JQ%>jyTH3=M>NaXL z8cZ5jpswiI`k^^@ss+o)+@0;7jvn^H`K0B0HNTrEA68N^Sp{1a?vw?)gh?=WAir_a z3X#R>q(wjX<=T$;y8hv~^kE7kAxo}%%j0ThJiWRkXKABWs5K_+g~9FzEsdIAOK2wC z(4g+FcSLdOkYcJUv)7}omR4&$gB*biSa03B^p{mz2g7$UdfN`9Q z4?PyaTZH9Ct4J0wi;%q#h{9r3ih|hMAf0h*6POrCMOFQa662KusJqp{7{S;+WfCv&U9g@gSiRy zyny#@KE|D?K<5|3tAwWr5U$?}oA~A&I^#a3sWI%9$IJ_9&{_@;HjF#zn|WK~9>n;M z57VV+CVn1~c*^ic-X?u>?wxVXId>qDM`zD~Ruz0abI!y!^T3X)DUJMw&bV6;&NJ)` zZ03uNYv#L>?`>R@Uz4DLjr;ke_-20G zxcA{B1ovaoHMl-_-07Qh8I6k#x(N@<%Kdy90OOl%n)!C)KA#l9$ZdGsnH1m5%Nv&` zb-AA;c5+OcJAE^MZ`^%J5t7sY4w!T9+0-vH&wp&CN;R3@z{Y(FWcWzQiEqxSeBp15 z|F4M4x@Xci>jo!u{2Z-VlMR!uDaY#(m-#pG&HBQr3xLGqm*4o0iErGO5#)~VtV5Kk zIQtmrdQ3dyzK$?={C(wqq25<6j?>;06mNe9{xv-0W#l*WpEv3F#?BdfldggL;bHnE z2BBROKY96ww0w;FdzW7V^v}aO{bar-oUw3L!e>q`;;wkuQ$+l^v$ zg30lD5?L~iq`%*xB5?l3{Up=Q*71|``Q>I6>seFLG!qlw?V7glPG{>L1>MI5A3Xdj tb2a`<`I&O1eM!n9FnDfI&USXruE(TnQ26?9*!bIf6~)4&2uYyze*v@f6d3>j diff --git a/native/LinuxGlobalMenu/DbusMenuWrapper.c b/native/LinuxGlobalMenu/DbusMenuWrapper.c index 9fb340423803..ce62b421e9a8 100644 --- a/native/LinuxGlobalMenu/DbusMenuWrapper.c +++ b/native/LinuxGlobalMenu/DbusMenuWrapper.c @@ -20,6 +20,9 @@ static GMainLoop *_ourMainLoop = NULL; static jlogger _ourLogger = NULL; +static jrunnable _ourOnServiceAppearedCallback = NULL; +static jrunnable _ourOnServiceVanishedCallback = NULL; +static guint _ourServiceNameWatcher = 0; typedef struct _WndInfo { guint32 xid; @@ -28,6 +31,7 @@ typedef struct _WndInfo { DbusmenuServer *server; DbusmenuMenuitem *menuroot; jeventcallback jhandler; + GList* linkedXids; } WndInfo; static void _error(const char *msg) { @@ -65,16 +69,30 @@ static void _printWndInfo(const WndInfo *wi, char *out, int outLen) { wi->registrar, wi->server, wi->menuroot); } -void runDbusServer(jlogger jlog) { +static void _onNameAppeared(GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer user_data) { + if (_ourOnServiceAppearedCallback != NULL) + (*((jrunnable) _ourOnServiceAppearedCallback))(); +} + +static void _onNameVanished(GDBusConnection *connection, const gchar *name, gpointer user_data) { + if (_ourOnServiceVanishedCallback != NULL) + (*((jrunnable) _ourOnServiceVanishedCallback))(); +} + +void runDbusServer(jlogger jlog, jrunnable onAppmenuServiceAppeared, jrunnable onAppmenuServiceVanished) { // NOTE: main-loop is necessary for communication with dbus (via glib and it's signals) _ourLogger = jlog; _ourMainLoop = g_main_loop_new(NULL/*will be used g_main_context_default()*/, FALSE); + _ourOnServiceAppearedCallback = onAppmenuServiceAppeared; + _ourOnServiceVanishedCallback = onAppmenuServiceVanished; + _ourServiceNameWatcher = g_bus_watch_name(G_BUS_TYPE_SESSION, DBUS_NAME, G_BUS_NAME_WATCHER_FLAGS_NONE, _onNameAppeared, _onNameVanished, NULL, NULL); _info("glib main loop is running"); g_main_loop_run(_ourMainLoop); } void stopDbusServer() { g_main_loop_quit(_ourMainLoop); + g_bus_unwatch_name(_ourServiceNameWatcher); // _info("glib main loop is stopped"); } @@ -120,8 +138,8 @@ static void _onDbusOwnerChange(GObject *gobject, GParamSpec *pspec, gpointer use GError *error = NULL; g_dbus_proxy_call_sync(wi->registrar, "RegisterWindow", g_variant_new("(uo)", - wi->xid, - wi->menuPath), + wi->xid, + wi->menuPath), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); if (error != NULL) { _logmsg(LOG_LEVEL_ERROR, "Unable to re-register window, error: %s", error->message); @@ -141,6 +159,19 @@ static void _releaseMenuItem(gpointer data) { } } +static void _unregisterWindow(long xid, GDBusProxy * registrar) { + // NOTE: sync call g_dbus_proxy_call_sync(wi->registrar, "UnregisterWindow", g_variant_new("(u)", wi->xid), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error) + // under ubuntu18 (with GlobalMenu plugin) executes several minutes. + // We make async call and don't care about results and errors (i.e. NULL callbacks) + g_dbus_proxy_call(registrar, + "UnregisterWindow", + g_variant_new("(u)", xid), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, + NULL, + NULL); +} + static void _releaseWindow(WndInfo *wi) { if (wi == NULL) return; if (wi->menuPath == NULL) { @@ -162,10 +193,21 @@ static void _releaseWindow(WndInfo *wi) { } if (wi->registrar != NULL) { + _unregisterWindow(wi->xid, wi->registrar); + if (wi->linkedXids != NULL) { + for (GList* l = wi->linkedXids; l != NULL; l = l->next) + _unregisterWindow(l->data, wi->registrar); + } + g_object_unref(wi->registrar); wi->registrar = NULL; } + if (wi->linkedXids != NULL) { + g_list_free(wi->linkedXids); + wi->linkedXids = NULL; + } + free(wi); } @@ -255,6 +297,43 @@ WndInfo *registerWindow(long windowXid, jeventcallback handler) { return wi; } +void bindNewWindow(WndInfo * wi, long windowXid) { + if (wi == NULL || wi->server == NULL || wi->menuPath == NULL) + return; + + GError *error = NULL; + g_dbus_proxy_call_sync( + wi->registrar, + "RegisterWindow", + g_variant_new("(uo)", windowXid, wi->menuPath), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (error != NULL) { + _logmsg(LOG_LEVEL_ERROR, "Unable to bind new window, menu-server '%s', error: %s", wi->menuPath, error->message); + g_error_free(error); + return; + } + + if (wi->linkedXids == NULL) { + wi->linkedXids = g_list_alloc(); + wi->linkedXids->data = windowXid; + } else + g_list_append(wi->linkedXids, windowXid); +} + +void unbindWindow(WndInfo * wi, long windowXid) { + if (wi == NULL || wi->server == NULL || wi->menuPath == NULL) + return; + + _unregisterWindow(windowXid, wi->registrar); + + if (wi->linkedXids != NULL) + g_list_remove(wi->linkedXids, windowXid); +} + static gboolean _execReleaseWindow(gpointer user_data) { _releaseWindow(user_data); return FALSE; diff --git a/native/LinuxGlobalMenu/DbusMenuWrapper.h b/native/LinuxGlobalMenu/DbusMenuWrapper.h index 3989eaa93780..1673ce94a121 100644 --- a/native/LinuxGlobalMenu/DbusMenuWrapper.h +++ b/native/LinuxGlobalMenu/DbusMenuWrapper.h @@ -37,13 +37,16 @@ extern "C"{ // runs main loop of glib (which is needed to communicate with dbus) // must be called from java thread (to avoid detach, so jna-callbacks will be invoked from same thread) -void runDbusServer(jlogger jlogger); +void runDbusServer(jlogger jlogger, jrunnable onAppmenuServiceAppeared, jrunnable onAppmenuServiceVanished); void stopDbusServer(); void execOnMainLoop(jrunnable run); WndInfo* registerWindow(long windowXid, jeventcallback handler); // creates menu-server and binds to xid void releaseWindowOnMainLoop(WndInfo* wi); +void bindNewWindow(WndInfo * wi, long windowXid); +void unbindWindow(WndInfo * wi, long windowXid); + void createMenuRootForWnd(WndInfo *wi); void clearRootMenu(WndInfo* wi); void clearMenu(DbusmenuMenuitem* menu); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/GlobalMenuLinux.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/GlobalMenuLinux.java index cdd2ad8d5fc2..a55def588326 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/GlobalMenuLinux.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/GlobalMenuLinux.java @@ -29,18 +29,26 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; import java.text.SimpleDateFormat; import java.util.List; -import java.util.*; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.Date; interface GlobalMenuLib extends Library { - void runDbusServer(JLogger jlogger); + void runDbusServer(JLogger jlogger, JRunnable onAppmenuServiceAppeared, JRunnable onAppmenuServiceVanished); void stopDbusServer(); void execOnMainLoop(JRunnable run); Pointer registerWindow(long windowXid, EventHandler handler); void releaseWindowOnMainLoop(Pointer wi); + void bindNewWindow(Pointer wi, long windowXid); + void unbindWindow(Pointer wi, long windowXid); + void clearRootMenu(Pointer wi); void clearMenu(Pointer dbmi); @@ -100,11 +108,14 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { private static final GlobalMenuLib ourLib; private static final GlobalMenuLib.JLogger ourGLogger; private static final Thread ourGlibMainLoopThread; + private static final Map ourInstances = new ConcurrentHashMap<>(); + private static boolean ourIsServiceAvailable = false; private final long myXid; + private final @NotNull JFrame myFrame; private List myRoots; private Pointer myWindowHandle; - private GlobalMenuLib.JRunnable myGlibLoopRunnable; // only to hold runnable object until it executed + private boolean myIsProcessed = false; private final EventFilter myEventFilter = new EventFilter(); @@ -120,7 +131,7 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { LOG.error(msg); } }; - ourGlibMainLoopThread = new Thread(()->ourLib.runDbusServer(ourGLogger), "Glib-main-loop"); + ourGlibMainLoopThread = new Thread(()->ourLib.runDbusServer(ourGLogger, GlobalMenuLinux::_onAppmenuServiceAppeared, GlobalMenuLinux::_onAppmenuServiceVanished), "Glib-main-loop"); ourGlibMainLoopThread.start(); } else { ourGLogger = null; @@ -130,12 +141,14 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { public static GlobalMenuLinux create(@NotNull JFrame frame) { final long xid = _getX11WindowXid(frame); - return xid == 0 ? null : new GlobalMenuLinux(xid); + return xid == 0 ? null : new GlobalMenuLinux(xid, frame); } - private GlobalMenuLinux(long xid) { + private GlobalMenuLinux(long xid, @NotNull JFrame frame) { LOG.info("created instance of GlobalMenuLinux for xid=0x" + Long.toHexString(xid)); myXid = xid; + myFrame = frame; + ourInstances.put(myXid, this); } @Override @@ -149,6 +162,20 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { } } + public void bindNewWindow(@NotNull Window frame) { + final long xid = _getX11WindowXid(frame); + if (xid == 0) + return; + ourLib.bindNewWindow(myWindowHandle, xid); + } + + public void unbindNewWindow(@NotNull Window frame) { + final long xid = _getX11WindowXid(frame); + if (xid == 0) + return; + ourLib.unbindWindow(myWindowHandle, xid); + } + public void setRoots(List roots) { if (ourLib == null) return; @@ -168,29 +195,36 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { myRoots = newRoots; _trace("set new menu roots, count=%d", size); + myIsProcessed = false; + ourLib.execOnMainLoop(ourProcessQueue); + } - myGlibLoopRunnable = () -> { - // Glib-loop + private void _processRoots() { + // exec at glib-thread + if (myIsProcessed) + return; + + myIsProcessed = true; + + if (myWindowHandle == null) { + myWindowHandle = ourLib.registerWindow(myXid, this); if (myWindowHandle == null) { - myWindowHandle = ourLib.registerWindow(myXid, this); - if (myWindowHandle == null) { - LOG.error("AppMenu-service can't register xid " + myXid); - return; - } - } - - ourLib.clearRootMenu(myWindowHandle); - - final List croots = myRoots; - if (croots == null || croots.isEmpty()) + LOG.error("AppMenu-service can't register xid " + myXid); return; - - for (MenuItemInternal mi: croots) { - mi.nativePeer = ourLib.addRootMenu(myWindowHandle, mi.uid, mi.txt); } - }; + } - ourLib.execOnMainLoop(myGlibLoopRunnable); // TODO: clean ref myGlibLoopRunnable + ourLib.clearRootMenu(myWindowHandle); + + final List croots = myRoots; + if (croots == null || croots.isEmpty()) + return; + + for (MenuItemInternal mi: croots) + mi.nativePeer = ourLib.addRootMenu(myWindowHandle, mi.uid, mi.txt); + + if (!Registry.is("linux.native.menu.debug.show.frame.menu", false)) + ApplicationManager.getApplication().invokeLater(()->myFrame.getJMenuBar().setVisible(false)); } private MenuItemInternal _findMenuItem(int uid) { @@ -448,30 +482,10 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { public static boolean isAvailable() { return ourLib != null; } - private static boolean _isLinuxEnvSupportsGlobalMenu() { - if (!SystemInfo.isLinux || !Registry.is("linux.native.menu")) - return false; - - if (!Registry.is("linux.native.menu.debug.check.desktop")) - return true; - - String desktop = System.getenv("XDG_CURRENT_DESKTOP"); - if (desktop == null) - return false; - - desktop = desktop.toLowerCase(); - return desktop.startsWith("unity") || desktop.startsWith("ubuntu") || desktop.equals("kde"); - } - private static GlobalMenuLib _loadLibrary() { if (!SystemInfo.isLinux) return null; - if (!_isLinuxEnvSupportsGlobalMenu()) { - LOG.info("skip loading of dbusmenu wrapper because not-supported desktop used: " + String.valueOf(System.getenv("XDG_CURRENT_DESKTOP"))); - return null; - } - UrlClassLoader.loadPlatformLibrary("dbm"); // Set JNA to convert java.lang.String to char* using UTF-8, and match that with @@ -629,6 +643,7 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { private class EventFilter { private Timer myTimer; private long myLastFirstRootEventMs = 0; + private GlobalMenuLib.JRunnable myGlibLoopRunnable; boolean check(int uid, int eventType, @NotNull MenuItemInternal mi) { final long timeMs = System.currentTimeMillis(); @@ -717,7 +732,7 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { } @SuppressWarnings("deprecation") - private static long _getX11WindowXid(@NotNull JFrame frame) { + private static long _getX11WindowXid(@NotNull Window frame) { final ComponentPeer wndPeer = frame.getPeer(); if (wndPeer == null) { // wait a little for X11-peer to be connected @@ -806,4 +821,28 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { else LOG.info(msg); } + + private static final GlobalMenuLib.JRunnable ourProcessQueue = () -> { + // exec at glib-thread + if (!ourIsServiceAvailable) + return; + + for (GlobalMenuLinux gml: ourInstances.values()) + gml._processRoots(); + }; + + private static void _onAppmenuServiceAppeared() { + // exec at glib-thread + ourIsServiceAvailable = true; + ourProcessQueue.run(); + } + + private static void _onAppmenuServiceVanished() { + // exec at glib-thread + ourIsServiceAvailable = false; + for (GlobalMenuLinux gml: ourInstances.values()) { + gml.myWindowHandle = null; + ApplicationManager.getApplication().invokeLater(()->gml.myFrame.getJMenuBar().setVisible(true)); + } + } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java index cfc960ad7f01..955a29054ee9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java @@ -16,9 +16,11 @@ import com.intellij.openapi.actionSystem.impl.WeakTimerListener; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.ui.FrameWrapper; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.registry.Registry; +import com.intellij.openapi.wm.IdeFrame; import com.intellij.openapi.wm.ex.IdeFrameEx; import com.intellij.openapi.wm.impl.status.ClockPanel; import com.intellij.ui.ColorUtil; @@ -35,10 +37,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.Border; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; +import java.awt.event.*; import java.awt.geom.AffineTransform; import java.awt.geom.GeneralPath; import java.awt.geom.RoundRectangle2D; @@ -558,13 +557,34 @@ public class IdeMenuBar extends JMenuBar implements IdeEventQueue.EventDispatche frameMenuBar.myGlobalMenuLinux = gml; Disposer.register(frameMenuBar.myDisposable, gml); frameMenuBar.updateMenuActions(true); - if (!Registry.is("linux.native.menu.debug.show.frame.menu")) - frameMenuBar.setVisible(false); } } else if (frame.getJMenuBar() != null) LOG.info("The menubar '" + frame.getJMenuBar() + "' of frame '" + frame + "' isn't instance of IdeMenuBar"); } + public static void bindAppMenuOfParent(@NotNull final Window frame, IdeFrame parent) { + if (!GlobalMenuLinux.isAvailable()) + return; + if (!(parent instanceof JFrame)) + return; + + final JFrame fr = (JFrame)parent; + if (fr.getJMenuBar() instanceof IdeMenuBar) { + final IdeMenuBar frameMenuBar = (IdeMenuBar)fr.getJMenuBar(); + if (frameMenuBar.myGlobalMenuLinux != null) { + frame.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + frameMenuBar.myGlobalMenuLinux.unbindNewWindow(frame); + } + public void windowOpened(WindowEvent e) { + frameMenuBar.myGlobalMenuLinux.bindNewWindow(frame); + } + }); + } + } + } + private static class MyExitFullScreenButton extends JButton { private MyExitFullScreenButton() { setFocusable(false); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java index 433780d22002..e54b7605e622 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java @@ -1990,6 +1990,9 @@ public class ToolWindowManagerImpl extends ToolWindowManagerEx implements Persis hideToolWindow(Objects.requireNonNull(info.getId()), false); } }); + + final IdeFrame parent = WindowManager.getInstance().getIdeFrame(myProject); + IdeMenuBar.bindAppMenuOfParent(window, parent); } @Override diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 7f7117f3f48b..bd504de65aaf 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -858,8 +858,6 @@ ide.mac.message.sheets.java.emulation.dialogs=true ide.mac.message.sheets.java.emulation.dialogs.description=Use Java message sheets based on awt dialogs instead of native sheets linux.native.menu=true linux.native.menu.description=Enables native menu on Ubuntu -linux.native.menu.debug.check.desktop=true -linux.native.menu.debug.show.frame.menu=false windows.jumplist=false windows.jumplist.description=Enables JumpLists on Windows