This makes the keyboard navigation feel more solid.
I'm not bothering to do the same for panning with the mouse. Mostly because I'm lazy, but also as an escape hatch in case I find myself wanting to move the top lower down the screen or something. But it'll still snap back the first time I pan using the keyboard. Let's see how much it matters.
ZHEJFKSLMORNRVOM7ZY7P4WAXIKGTQ5JVRJRWICXNXKF6HJWEFCQC R5HNWYMH47LWVHS5VVXNR6TCBDXDURVXZ6RCUNFTTTMIXF275ULQC R5QXEHUIZLELJGGCZAE7ATNS3CLRJ7JFRENMGH4XXH24C5WABZDQC OF4P6TYQA7SUF4N2KPDN7LRTIRNXME2IZJHRLFGF3EMDTWZSGOYAC ZXQ2MMPAOIA4TN3TWMFPXZUL7NUE3EWXLV2JHBQXEINE7WCKFSIQC 7TQAF4BYIK75EEYCCK7VEUSZHNCWMWIA3HZGQKIILYESUZ5ZZRVQC BF7TW3EKRIDYC6J2Q2J4YOBAVQF55Y3H6KGZIHNXMH4N72MR6GXQC VZ6UKPE6CW7ZUKUBPUY3XAZL37WILDOTUZLNOM7NZGHS7WVQAXLQC X7HYGAL2QVKG7M5EMZ2VSH37UYWGE3EPUXYQBJOVL6IGJFZ2I5AAC compute_viewport_bounds = function()local xmin, ymin, xmax, ymaxfor i,node in ipairs(Surface) doif node.type == 'text' or node.type == 'rows' or node.type == 'cols' thenif xmin == nil or xmin > node.x thenxmin = node.xendif xmax == nil or xmax < node.x+node.w thenxmax = node.x+node.wendif ymin == nil or ymin > node.y thenymin = node.yendif ymax == nil or ymax < node.y + node.h thenymax = node.y+node.wendendendxmin, ymin = xmin-50, ymin-50Viewport_bounds.xmin, Viewport_bounds.xmax, Viewport_bounds.ymin, Viewport_bounds.ymax = xmin,xmax, ymin, ymaxend
Viewport_bounds = {}
Viewport.x = Viewport.x + scale(50)B()elseif chord == 'pageup' thenViewport.y = Viewport.y - App.screen.height/Viewport.zoomB()elseif chord == 'S-up' thenViewport.y = Viewport.y - App.screen.height/Viewport.zoom
Viewport.x = math.min(math.max(Viewport_bounds.xmin, Viewport_bounds.xmax - App.screen.width/Viewport.zoom),Viewport.x + scale(50))
elseif chord == 'S-down' thenViewport.y = Viewport.y + App.screen.height/Viewport.zoom
elseif chord == 'pagedown' or chord == 'S-down' thenViewport.y = math.min(math.max(Viewport_bounds.ymin,Viewport_bounds.ymax - App.screen.width/2/Viewport.zoom), -- conservative; unclear why removing the '/2' makes the bottom inaccessibleViewport.y + App.screen.height/Viewport.zoom)