diff --git a/autotests/data/simple-multipage.pdf b/autotests/data/simple-multipage.pdf new file mode 100755 index 0000000000000000000000000000000000000000..eff96927de2e0b7b00047dd22a9fbff79281a5b6 GIT binary patch literal 18473 zc$~$XbyQr-md0^+mjny$jT7A6-QC^Y9fG^NLvRle+=FXy4eoA}JMZ1OGb^k$lDFpe z>OW4MKJx4RRegI`cO4R0L17vIEi(+s#7y4;3?l(OfsMX73@0ZHourYqiK8h2J3YZa zUodpSW|odd_5^gomU@mxf<^{5hDI>l+%OJ~_C|VEFs@4^!&C^q^hn^mYYG*XLdhM+ zCS7s9yo7VeV9?o*YrbGtqo$wJ<)GJdl?mIR9v{+l{B+?zgmi0FD&}elO)Bqd`1bt z(#PWiTNi>Dqk+2e1}N+Af>NRU1pOnVf{l5(bk7B<#=JR5c5wdK+_#;;AnhEfxEP8c zt`$myc>ct+B=My5;$&^6w;D*-dmbSvg>D4z8c~?+Y|u31e@4{Dp{@lnCJc4$S5PMU zzZq1N&631)bCtZYpu*qhW!KmNKc)$F;|G_(X5JoTZo=`0LZy*e-X> z4(iq$pntdY3BQ2GqN48n3d;Og0m||>gPQ&_m|`);CJh|0U=jeH7>)qp9$? z)kzfviCpkKU(8v{D?HMVTT;ZHZuAtp3Z<|3x`c`}y1j!-U33duNxeV&Cx;7KHD1=>FZc!={I=it-n&!RJR$f>W7B# zTwxOQle%<`(dXF5w+x^Cx91}NReJ6fYG^35yeINU^_7FTh`4DcX>jduIjC(+A$i|{BI#;6 z!~EBzsqHPp2hjh`73uw_Uu*pRw;Ufp|NG+q9x3&&mXGU9{J#3Xm7Qu#KYD_*bgvSyGB9oYqk@Wcc+2zwfZv~x{8oB;i!}Ew*9QQ8 ze@60K`Kdo|{|tQrs*PXyFVgY1Y##vlo6FMsieE?6^IN_TVEFxiAAWE0R2nqR;xBBS z7>twn=bR*t>MiF7F#L<<|KH}QhnXHT+-j6Yn3}jem}vIVpYyypHPp+uNPl1c-z!Zi zeyR9k4&Su?H-0Sz5CE82S^jJ>5U?@O)BoA}*;)STB@E1r|I;rNSr5td&JvZSA_7Ir zQQ6Ud)%b1Q-94Adltod1tJ!7x0MkFn%(`JQo{r!s*as%R*mq)qv4guw*l|>uHfP*v* zm_(3GPDi!s`UWHrNCOvs^HPPjT#I1JB(E+zF+HsSbhJt8%ey#oxeV&sJ%IoOT7rwV z0~`e8%?vjI+{XLrNXk11OmFYo^4tZF>})DS4+GN-oT1k!+x%TBkmDVQ5U@1@B$hcR z&<~>AGoEcoAE;X(pD_pmVuCA|*3LX168|nA$N(!VWLi=BWn73R$c3(qTp+CmNDx!H zD=r``gnJ<{jy6K;%`QCM6vlMsh5aW72g9hnLyB^(rP- z1?3=t1Y}xTS+=FfGZimNdbF7vq-YLvqdM zA_O{{-#hh5V!iMuSpT;AI^nZcl~Wts65au`mL2taLqS3K1*qeRC=bY64?yUfP(aMf z4+nMjdP?oCyP%^4^a?%e`<)O--Y2|0b;<|k=I-#N<#h=j@2k(=6yI_v2F&`4$X2wk zKJWK*y4+Wj!dHa*SJb;I>Q~mtR~tU_lW*TTSC%`UU-4NNz;}-U)T9VN`Len;{Ogf1 zfqlI|9sI22P=4;ubM(BjKvBGFfk4(vmyipDvVon}iYQP>GmqfUjRnL&{_CAIxw!4n z{I4uF7qBn;FE)Z;1g4OecbGzV5WLO#FNvGM`mfQiq&!bWRh__c6utzTIyX|Y{?@Y5 z>6m*qf>#hNi-DcT>1h)P};EwPiKBQ^f)+B})vPOh?Q}Lc8L9tW>Qt492e55j#)e%4VN4z<7d+H-*lK4zLoY zUb8H{g%Te{?UHt;T=uMJyag3%y)R`tBL>1C@-4;!r}0m(K7CmNo^@nIroX_Y`248V z`j867uGiUTIlVn-=afu5Ig-zLeI$QdwojXd3zw}qty6_GPt;0|w-wDC<%Xun))i}U zd4YPY#mU4oO`{#oMK=|ezhxJG6l;MoCdkeIT2(^?-hm;}ZD*40$(@V?-PSN&Gp#nk zpocF97iIrIX;oxCC3%m5PMrra&AnpwUftP^bodkGe*xjOh^xmQ= zSDd;9N1ma=7-ndhtDV&^yLrj|e!UvFO&+ac)fQSNVK@L#qSA(_%Ojj@DNpMIbH-ID zP{@M>91PcDRWMXzXLvF(!oUuHI@`~4EC$xGyBNb+>I65-w8K|Di$nHZiqP}k5;vFDOqScAe0hzL^}w4 zglzG7xKAp8sr20jpQ9cIjLZ_j!$Xb62Aio)&b|mt*WQK*oFa5;>|TNzfrlT%CyItS zWn{~#8}5^G-f?H)lJ)D7D18@mBGD?D?Tt9Rm5QWiyIN{ugrUbpR^=>pw~3`aEVh8f zi1aM~FhMzHLDrz&`4~P@;b6h4OGRA+OF-K#d#)B3?jiI)Z)}^80t*yU^a<6T|jWbq3C747VszKZ?a2?g@bUq70a5cJ`3~lbarW^sP_vq12 z4=L2Om>>sQ4Z&v^bP=a(+9WII*yB$WXH#cpwKs?uS!e8vFTp7`c**Wt2!58e{5Y1a z(eumPo#rP83LG^qRY#hO?FMz*Yy%eo!BXtCX9Dgt!eMQg`33w7huP z>;J^qag01@B2ieWSXT2Lrd{kNNcZ&NG-rM`U%4EIk5!mITUxA+|Dw z6O{Q!59-PVWaf)S?R>t*bFnR85)-=W!qQL%!W61RABsz<24bUOa`i2o?LLl_@s81t zHskufQXV`LNC7p1{W(2g2J@~IXXPN}mxrpysZ(-#9^xxw?7(I8`Ltn%OPB8BvD-j+ zK}`$b!%Y|t@=}&1#1$QEM#k;zQwbCe?NTMvFQ0DDZX_!{8ay7VNHBV*ilJtX#`afz zwh9@>ykrr3h{zxVNs8|qc*oFdhmQg^PCe%}Dy?f=qk2LA5_{g)A~YTyFi_AG+iO&1 zR<=!o3Lf;%1UAJs|LPm!ShIA~UT$>i1!Q^rlwJE4i1CkSPk8@J{k}HyI*6%+sZEl1 z%+f#315AlP9-9*h8zbsl-E3D6|b^Z6fT+0F6+CdfuRLHL50&?6!mw z1Il+_CSWx`|1>BWk{HD(9qccM(l&g?tTS45=qJ6!v;sU!GmQXMuc z--$A2qTRydBlcI;kaK9LZNNW_&t0~OQ?NwR@>gL(p_QjqX>aW@-3fV^i{!^yl@?%J zm$azV8Dh8AIut`=Kic&M=8g|fC7Yl?6=$wW@tgt~AOlcJ^9 zGU1HY27e;Tg`Wfvzud(n*1;t+_}NvabA3IX4ugeE`XYB2s<3lWNt58ATG*1u!r9v8 zwJ?(=;FqPS6Sp5y+#1TIu%0Lhi(CLyWw+`E#78gqs(cs6w&;3)HrTH9G~%!`RQ&F0 zWmi~46M{$IegFLceJyf4zvNP%?JK0pxhIy#&{V66lYhV*SvVo?*5a0(#SGTWb6%uf z14&vSajtl;4CLd2#AsJG<*5RyFAC_9p9|Af_T>9v+QIe0=c}{$74(5@*=#i>!GYGa zpn*ZU+kp?vro(KMEvaMPt_5%v5_hn(;(8yGeJSgWM?e8;y|9Beg+=P5E-~ju8FWhQ zWG}AN(q4m!;!T%whO0|q^P$aIZBLO#%4DU@DP2sjJqXsbwN(UC%E+u{n&fokHXhtQ zFba<2aasE0dh6^@`;r!K>cHR z@lg%ch)dkcurV|6u^o!e66**9HUYuYGHI!1SAN8lrb&tnW2H%mrkx`aunJc~LjRXfoGJhII$C<{aFCkwU_cmTS}gm)TrcCaRFQt~-vk z!CJhk8t|d?*+vk8#xv(9d+Xp0mEx6q6Ie+u<-FvXMI8I_mJ3wlQa2tw5tS3Ac`pe1 z6TLx?A7e{CKN{hH-#X%+^|d6y{74cR%)B&L?Pi1)sOoWYY%()h{PGnG4762Ptx0n3 zF1-a;mH7~ddetqR2BjXOMqT+%a*RqEdIqwCJ)acgdt^7(MzoBwn=I807PEtoRr%;F zcXKs=40eMYmSm$Dk7DjX?9&XaEX<;{gw^eEDv;LFi6albDbCPX8-0l9F2YXYw~s=- z{1qQAFL;;s+*xt~8&78{VaOWjrWwQ%jjjGAcqSg-UhGWe)Uo%C%ObG??Gsc~5_zdN zoD*wed)QY@Orlvzje`d`Q%q1D1CB&@Mn7e}CuQj1I}tu+^OvEibLWxDBHbr)fOMa1 z9G;WPw(kI9+-fZY9U}kkXm$Y z#L9SL29=Z-I|_GcCu173fL<*doXUMbl@K~r@1TGjmM*kox}7aU=AK3%WuQwc<{le! z(AS{6Rs6y0OgpcQNaCVRn}4Xis+VSA;zbQ+ihb&zQ|1LrOVBGubsIN;hDd#1bcm{v zpSUOLwTjm@~sNv%uHOhYmPl;M)pOIwU$6hsGMFm^2*RG9RDcVErmcWv<>}0ipL{!UB%sv~rmx%c5JwsS@}gH^Q9lU30% zhc~lchP4);r*~)5xI*j3(sod^x5rTCVs?Un&4t{MlolS~r^`;^`R?W#n?J=+=*GbT z0IY0?Zg6^xAWyvuMRyDq$wJjVhi`$HyGj5qo*28-4q>B4urXfaPXwz6P!NI<+$3(Zu(4reZh@ zKAA`O@i=yrpt<95St1RIhG^CGH4r2dHwHB85UUMW0~IRy=7-iY8FI{dXeSN;-yxJQ z-q9$)Yrr=rj&%&*y~GYydaa^ZJiE-qk1e|C!{nk^Z|@$Q0YmaCdYQWFt)(=26UWTC z+h#SEr-DN`5PX|OVw~|siQ(P&j6pUWi2nXMap&r#_tSON6iA1FiUDSbi!CirpE&W; zsrz2L)5VAa4RgFtq+CErOWY2RH1#IU!_0I9s z3%SIi$%mlV8d+a)?|>0|^R6i7oWb#h4H_7xxFrz~W|(b5Fs3vIt4duWkxW(UZOq(j03Po7-# z+-7#UX7}7~U5NMupkFbiNcvi3IH zH=e8WW6*a6pNAwKyf!oSs3)S$6&A}OCzXMw!=Pv6XXHHb>IANzdOzn`Twkh%p7HOL z-&Tt$e(oi=W`i`qD^$7q5o7AtJFPW@2;Y|Lr-ba~rY|kSEvD1Zp?EI1N)v0hTm`m~ zk&Fzdfs4ag#yUV)ih^}Hqn6jA_*vXh{j!MKt#;iz+bTjM&QMS!4`Q9KmAr(nN79h4 zE){O3G50zPbt$d?hVO%;c}R~XAf=b_F4FP%j*rarQlP(Wa0QsIOluLiL)FB`7OjicABuCrm^fhdTuZ3mC06%ty<`-26mfk zR~N-;sUob5yeAEqSG}WOn|-uw$U_iZ)=OcByIGM@hay=!m+6F`<)R|$S&J@V$81XIqvF0>2M<}B3==zV_)m}(h@#} zG>@HK?IpQ<(i7)|1U8QMV`BpH6hB}!oYSxxvW=bzlGM+V9Qm^h^qh~Z{0F&bm__fl z4Fo~EfPt^ITT6U;H@Om6@_xtVD&9C}cu{+;Al=2g1a*2ZN&T2E?+YIbG<5(LH=Cxd zQj!s+2C8GdWI5QzVx?Qk6_%+0W&E? zsPRY507v>lauYb>bALVjH{82Q1FR&<(6zzPDvRt#Cli+?9(E{B0Aw>JPlY}Ax^Vrd z=9U!L;&d@bd7SsPq_yc$3fvCtCurUm-_f}gc7?w3l$JW#9ivjzcB4k*xqkno743-4 zAZe*g+HSbr(J#bn{w&jq8^LH4(QqXW=k{Nw6$g^V0vOf|iaQbYY~Que$D!mse@@m6 zEi1{s*E8FmXFfoXyj5eEjbd4jDVG%O=MH4l^)5ohb{OUy`En564xSm>-h}=AdOra? zfv5DweyLP>Vs~UMGiu+*Ks5iOXJYelPY~p^4GKIYT0QXJV z7|EE8Lrv252yDPDBjNZ1*Jj(nvI}NtTPIq!7T#0fXLCq$XQW64`y?07r6Pfb#5X;s8LSl$eIRsEpbEuhg5o)s`4c}}s0e##W>!TJ)1 zu#&LY?lHIzB)({cO;|EL z*`g;LGJ{a1>piKDpxJWl92X^(idhOCA`^Rtv{g{JBwV4Eed2zzs>|(m%2VGoqh%~; zrv=k0!j!($?kM>O&#HQz)@;{97Cw!o;C;gmrOplrym#a$;Be`5)h!7_Ex{wDw}nqKT_Mr<7_G%dh5vnua_!ck8;8>k7Nk zUy%F=df+%axN(G}r{;e2ifH909n)D!Vmhc@I%2@YFwU%hv-wKgc89TdH-5Hj$FG#A zx~We5Qp6zc-gyxd=4rKA&W#KP)VO z>U6~_YK{*3+br=ZD*Kx9+JWKUEY4V1xP!7)9$cKEKHd{Da1ZIkNTi_u6;)3i?*VXC7b zq@qq+V_ep8o(OBOcQ9qPG8|_oy zn!j^@H{Q!*J&pW;YS3QCWUStF-38=z8$c0m7E{!|rI8C1Qdu7#43ucIL%%ERvQ+7! z7G~D$0)0i@Spc>!*lRKfS|=~4lBf86RyXf-j5RP^2VNIH0j+x*z$bhfsuuaq8ohzt zdYx`3{n3I&AS-)r)fn!#$GgoaEJX3oMTP6C~rt9nlMD z_R*$R!ml(V^ToK-kC42jSGJ@fl@D*8nISVh8frw0sYP%c0jCnI%pdZ)ckKoC6w@75 z=oug&PtL$S3j2q#S#*|cuZx8G_&dBk0u9)sI3c;lWkogIutI> zjw`Nou#n-A@$v5BL?eyiiDEkgMk$Qstf37fVRp-B#4vo~;BV})@jlfMM@f0$X4MrD z6`FGtz5j6k!p7OSKI={%KYq3Ha-2QKLb@r$qVgkmI$uEqjN zd!HK!)Gp?$B}37x>>s35CJHAkj<8`nGz5x$^1U*rB$9WJFKl+*a;c6A5qz%(E_0fE z-k`uO?I|^$ea;oqf}Cjitc`4CQ73KMCnYwBY zt7tFFsxTG`>T3#Y_ZF$8PeFy)(p18 zLq+?b9T*HMYYlUn1ptaxsrHoSbmZ6je1>RMBk{BQ`MU-L0mxJ5xQ;kIhw&Jtfwti1IS!QwH|>KBNPP6UiG|Nq zn?RG#`umsl?ZX@P8N>NR2JP?E$%P8g#LXitX_8{!V-xoD;MUad&~}wnEE3jw+7wS^ zNyLU0(jpwq>qMBM3eHx?Yj?eF*a-`gz4#YsyY+5;_uX7_&)Uh z5CHu$f*SagO1?f^I?nB_$DIJxfrc?_4~w4kw83K|pW7wy(T)=Pi#xeq-LASm=eIgm zzfiRZ@7(ODx!OcT2}w97CGi|$H5l~=WM&fEPuTjeQ0c_b2@Wl8zLCC?@v52$Xyr0W zRt>sRrd7YpKH7K=o=wQS@>7Y=P28n5S60Y7HCVAJe5qCWN7_34wvrM2Pl zW zhaYLSW#6mwjHZIcdZ*5@V`U5B;ldy~b0A$zc-(|^s=7Dcikp$Fk)ahc!WPjWztv{Wwd4Os@GPS5y#MfrGerJuwZyl3^4Oi)Go2WbJl&|P1?om z)h>Xf_kH51JGZtf9Q>@%));J8zxlXn3CMdjlf^0(;q`E@3mcajtXUGO~u7biV42p#ac|5HMqo5IIQ|&xN%c2 zXiw<4pY_w6Jw8fSa4LEB-9M`c-24E8WGltKEVRqqF60uDMTNeR8FFOL`5agWMcad< zCwz7_ZZ+jnyh4cSp#(R+oAo};{7@+h#GE)4b3bl2(dkxj%|Ny@!085Jd9h4en-T z&oLq+g%s=)SEsmg!(xGNvAG0G)>^cYebM;nKXv8O^s0ZDy{MU2$F7iKS`%`ly$7 zD?ix1aPbO+MLMML*5ai9yxLRN-p0_$z{s9}+}6-o(MXjBK+8l=3t*#wp%eIdmZQzj zPk!$HvuS2yEvV;cL_jY1k%1n-1^_Ss=-HT9nAxc40c7;_WIvCSvN8Pc4pFq%v$Zuc zB%l-4vve@}385&YN-OMSX{oPgZT$y}qN$k!!O!{ zoc>cJ6y0o%2KX(kGP{m8GZl{0Qm7sXELJo#f>HCZgLuJ z4YI>Ap8;EZkVN3FaJ|6VmGre?W8`1mA`jy{Qq$klBl}1J7lmtQouC0LS zBcUzU4LcYJU>SzOuOW;LxT{|pjRXfI=aMk~YZP#?=q9zEIa#b2l2d4wKM^Pkmi-WP zSD^$z&etod29}o@ib(JRgHJHRz&?=Ti$v1;u*W!kZ91z}M2I24M&0)ePw&5+~|{q$Ikz#}9_=UzNM0ofdV(p5BWm?YYqP#Y^6Qb&yP@9#zfarB2m)>aA( zbkvs|6!qYhhc98?$1uiF!pOuZ#vqD=kEYkFBuD432a}VQi+ho!SaAIQUF-F{s@(4( z;C^x9x@}}+%(g`>exT2G;X0(p-L3s2_FOYVfADS3zJ5pDleh>3e4Np4j+s7(#C>x> zGJ0@;TIAXn?B~-SGAkQ}&gku$8zlFKfZ2=fp6c8WqwP&H&jTBW!BI94&s2)uaOk+c z{E?i}iDtkOl+LrxSfUpctbYk7`H#)af9i}uBF zHA?4wuWkcZGq%iHA&L8n|Czh>CY9i*bS$1I!78B=Rq;>x zPm!Gr_7}%+9YHo;(H^3$BnI8bVcUU2=;sIzgx>55tVcq~);=v6CJL|TTvcxQ=X(2eO=j$21vR9pvnrr{u;3Cr+qkh+ z7O{idF3V3t`WD%x<4@f)1s@wLoIAdc(qWL<(2dhVFlfE%F?zlP`8z(_Ok>?((0<#a znte!r$;rMI;Bmgr#?T3VK{c=7Ii$l(7U=9X;qt_$eZ1bZ=w#P{7wEiqSbXKGNLs_# zdYS{apDE^=W4pio1P`tDa3qDUmH=Chn6GPW6)I{?cWJQcd;&x{Kq8 zkj)Z$c>p2)Fk$Bc2c{!!l&hnlJdV&XVf%syc?(pZ965A&As`8??@s@;bejlWq?DLE zxnC0{p(mn!FAjDkn`VIieeq3gTT%M1j8xZc(fXr;Do5g{bkD@5o-Mp1RPJXlYqyw7 zdD=b&w|3^|@+^!?R*T@*@TaeBUafJ9%Q!MdAA_DvCr;kortGMx2(L+lrTYK{=`nl0 zmB!e9F>h6QBV!mkF>6C3R{{tn94J^ejwFjC{;OOoB`T^a8>HOu_&`1_6MuAPYCa ze}9P9e`F0t0L%Y)l`{GOJ6(?*Q2+Vb<^1D>@@eboBXwn4WqRwZRPT2}{c2TehzKDf z6uOYmzOVY#P~(iA7oPYAquEAB1fZz&%Tn9ZOEi=pV0YElq*>M#kBK3vtCpl_Rb|ZS z++>~eZsHMHnpy>cDMOCscm(+tqG$EWe0xfxresize(800, 600); + part.widget()->show(); + QVERIFY( QTest::qWaitForWindowExposed( part.widget() ) ); + + part.m_document->pages(); + part.m_document->setViewportPage( targetPage ); + + /* Document::setViewportPage triggers pixmap rendering in another thread. + * We want to test how things look AFTER finished signal arrives back, + * because PageView::slotRelayoutPages may displace the viewport again. + */ + QTRY_VERIFY( part.m_document->page( targetPage )->hasPixmap( part.m_pageView ) ); + + const int contentAreaHeight = part.m_pageView->verticalScrollBar()->maximum() + part.m_pageView->viewport()->height(); + const int pageWithSpaceTop = contentAreaHeight / part.m_document->pages() * targetPage; + + /* + * This is a test for a "known by trial" displacement. + * We'd need access to part.m_pageView->d->items[targetPage]->croppedGeometry().top(), + * to determine the expected viewport position, but we don't have access. + */ + QCOMPARE(part.m_pageView->verticalScrollBar()->value(), pageWithSpaceTop - 4); +} + } // namespace Okular int main(int argc, char *argv[]) diff --git a/ui/pageview.h b/ui/pageview.h --- a/ui/pageview.h +++ b/ui/pageview.h @@ -198,6 +198,7 @@ QMenu* createProcessLinkMenu( PageViewItem *item, const QPoint & eventPos ); // used when selecting stuff, makes the view scroll as necessary to keep the mouse inside the view void scrollPosIntoView( const QPoint & pos ); + QPoint viewportToContentArea( const Okular::DocumentViewport & vp ) const; // called from slots to turn off trim modes mutually exclusive to id void updateTrimMode( int except_id ); diff --git a/ui/pageview.cpp b/ui/pageview.cpp --- a/ui/pageview.cpp +++ b/ui/pageview.cpp @@ -1331,36 +1331,15 @@ slotRelayoutPages(); // restore viewport center or use default {x-center,v-top} alignment - const QRect & r = item->croppedGeometry(); - int newCenterX = r.left(), - newCenterY = r.top(); - if ( vp.rePos.enabled ) - { - if ( vp.rePos.pos == Okular::DocumentViewport::Center ) - { - newCenterX += (int)( normClamp( vp.rePos.normalizedX, 0.5 ) * (double)r.width() ); - newCenterY += (int)( normClamp( vp.rePos.normalizedY, 0.0 ) * (double)r.height() ); - } - else - { - // TopLeft - newCenterX += (int)( normClamp( vp.rePos.normalizedX, 0.0 ) * (double)r.width() + viewport()->width() / 2 ); - newCenterY += (int)( normClamp( vp.rePos.normalizedY, 0.0 ) * (double)r.height() + viewport()->height() / 2 ); - } - } - else - { - newCenterX += r.width() / 2; - newCenterY += viewport()->height() / 2 - 10; - } + const QPoint centerCoord = viewportToContentArea( vp ); // if smooth movement requested, setup parameters and start it if ( smoothMove ) { d->viewportMoveActive = true; d->viewportMoveTime.start(); - d->viewportMoveDest.setX( newCenterX ); - d->viewportMoveDest.setY( newCenterY ); + d->viewportMoveDest.setX( centerCoord.x() ); + d->viewportMoveDest.setY( centerCoord.y() ); if ( !d->viewportMoveTimer ) { d->viewportMoveTimer = new QTimer( this ); @@ -1372,7 +1351,7 @@ horizontalScrollBar()->setEnabled( false ); } else - center( newCenterX, newCenterY ); + center( centerCoord.x(), centerCoord.y() ); d->blockPixmapsRequest = false; // request visible pixmaps in the current viewport and recompute it @@ -3805,6 +3784,35 @@ else d->dragScrollTimer.stop(); } +QPoint PageView::viewportToContentArea( const Okular::DocumentViewport & vp ) const { + Q_ASSERT( vp.pageNumber >= 0 ); + + const QRect & r = d->items[ vp.pageNumber ]->croppedGeometry(); + QPoint c { r.left(), r.top() }; + + if ( vp.rePos.enabled ) + { + if ( vp.rePos.pos == Okular::DocumentViewport::Center ) + { + c.rx() += qRound( normClamp( vp.rePos.normalizedX, 0.5 ) * (double)r.width() ); + c.ry() += qRound( normClamp( vp.rePos.normalizedY, 0.0 ) * (double)r.height() ); + } + else + { + // TopLeft + c.rx() += qRound( normClamp( vp.rePos.normalizedX, 0.0 ) * (double)r.width() + viewport()->width() / 2 ); + c.ry() += qRound( normClamp( vp.rePos.normalizedY, 0.0 ) * (double)r.height() + viewport()->height() / 2 ); + } + } + else + { + // exact repositioning disabled, align page top margin with viewport top border by default + c.rx() += r.width() / 2; + c.ry() += viewport()->height() / 2 - 10; + } + return c; +} + void PageView::updateSelection( const QPoint & pos ) { if ( d->mouseSelecting ) @@ -4644,11 +4652,10 @@ { int prevX = horizontalScrollBar()->value(), prevY = verticalScrollBar()->value(); - const QRect & geometry = d->items[ vp.pageNumber ]->croppedGeometry(); - double nX = vp.rePos.enabled ? normClamp( vp.rePos.normalizedX, 0.5 ) : 0.5, - nY = vp.rePos.enabled ? normClamp( vp.rePos.normalizedY, 0.0 ) : 0.0; - center( geometry.left() + qRound( nX * (double)geometry.width() ), - geometry.top() + qRound( nY * (double)geometry.height() ) ); + + const QPoint centerPos = viewportToContentArea( vp ); + center( centerPos.x(), centerPos.y() ); + // center() usually moves the viewport, that requests pixmaps too. // if that doesn't happen we have to request them by hand if ( prevX == horizontalScrollBar()->value() && prevY == verticalScrollBar()->value() )