Suggestion: keep canvas / content position unchanged when hiding and showing the interface

Hey there,
currently, when hiding the interface, whatever is currently visible in the canvas jumps to the side. In a similar fashion, when unhiding the interface, the canvas jumps back. I find it annoying that I need an additional step where I pan back to the area of interest.

I’d find it much more convenient if the canvas content stayed in place, and the UI hiding just revealed more of the canvas. Does that make sense?

Hello.

Discussions have been underway for this - if i remember correctly @AlansArtLog is already studying a way how do it. [Though i think he’s currently busy]
There are also limitations caused by QT [if i understand it correctly]

This is the last one - in where devs have drop by. You can visit it to see whats have been done about it at the moment :slight_smile:

2 Likes

Try adding this to TenScripts and using it instead:

from krita import *

action = Krita.instance().action('view_show_canvas_only')
qwin = Krita.instance().activeWindow().qwindow()
mdi = qwin.findChild(QMdiArea)
scrollArea = mdi.currentSubWindow().findChild(QAbstractScrollArea)
hbar = scrollArea.horizontalScrollBar()
vbar = scrollArea.verticalScrollBar()

changedVis = hbar.isVisible()
startPos = mdi.mapToGlobal(QPoint( 0, 0 ))


def posChanged():
    return True if hbar.isVisible() != changedVis else False

        
def newPos(posX, posY):
    if posChanged():
        hbar.setValue( -startPos.x() + posX )
        vbar.setValue( -startPos.y() + posY )
    else:
        QTimer.singleShot(50, lambda: newPos(posX, posY)) 


def restorePos(posX, posY):
    if posChanged():
        pos = mdi.mapToGlobal(QPoint( 0, 0 ))
        hbar.setValue( pos.x() + posX )
        vbar.setValue( pos.y() + posY )
    else:
        QTimer.singleShot(50, lambda: restorePos(posX, posY)) 

posX = hbar.value()
posY = vbar.value()
action.trigger()
QTimer.singleShot(50,
     lambda: newPos(posX, posY) if action.isChecked() is True else restorePos(posX, posY)   
)

PS if this approach works on all platforms, then it shouldn’t be too hard of a patch to fix natively.

thanx alot , its not perfect but almost

Not perfect as in? The flicker(which can be gotten around in plugin form or native), or is it a few pixels off?

Edit:

Just remembered that some people use subwindow mode, while at it I also made it adjust all open documents and take into account if a user decides to keep some guis in canvas only mode:

from krita import *

mode = int(Krita.instance().readSetting('','mdi_viewmode','0'))
#0 = sub Window
#1 = tabs

action = Krita.instance().action('view_show_canvas_only')
qwin = Krita.instance().activeWindow().qwindow()
mdi = qwin.findChild(QMdiArea)


subwins = {}
scrollArea = {}
hbar = {}
vbar = {}
startSubPos = {}
posX = {}
posY = {}

startPos = mdi.mapToGlobal(QPoint( 0, 0 ))

for subwin in mdi.subWindowList():
    view = subwin.widget()
    viewName = view.objectName()
    subwins[viewName] = subwin
    scrollArea[viewName] = view.findChild(QAbstractScrollArea)
    hbar[viewName] = scrollArea[viewName].horizontalScrollBar()
    vbar[viewName] = scrollArea[viewName].verticalScrollBar()

    if mode == 0:
        startSubPos[viewName] = subwin.mapToGlobal(QPoint( 0, 0 ))


        
def newPos(posX, posY):
    pos = mdi.mapToGlobal(QPoint( 0, 0 ))
    if pos.x() != startPos.x():

        for viewName in subwins:
            if mode == 0 and (subwins[viewName].windowState() == Qt.WindowMaximized) is False:
                subwins[viewName].move(startSubPos[viewName] - pos)
            else:
                hbar[viewName].setValue( -startPos.x() + pos.x() + posX[viewName] )
                vbar[viewName].setValue( -startPos.y() + pos.y() + posY[viewName] )
    else:
        QTimer.singleShot(50, lambda: newPos(posX, posY)) 


def restorePos(posX, posY):
    pos = mdi.mapToGlobal(QPoint( 0, 0 ))
    if pos.x() != startPos.x():
        for viewName in subwins:
            
            if mode == 0 and (subwins[viewName].windowState() == Qt.WindowMaximized) is False:
                subwins[viewName].move(startSubPos[viewName] - pos)
            else:
                hbar[viewName].setValue( pos.x() - startPos.x() + posX[viewName] )
                vbar[viewName].setValue( pos.y() - startPos.y() + posY[viewName] )
    else:
        QTimer.singleShot(50, lambda: restorePos(posX, posY)) 

for viewName in subwins:
    posX[viewName] = hbar[viewName].value()
    posY[viewName] = vbar[viewName].value()
action.trigger()
QTimer.singleShot(50,
     lambda: newPos(posX, posY) if action.isChecked() is True else restorePos(posX, posY)   
)