Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keep cursor shape while pressed as it moves outside its MouseArea

I am implementing narrow resize handles which give me annoying behavior. The cursor shape is as expected while the mouse is directly over the handle, but once dragging the handle is initiated, the cursor shape becomes inconsistent. There are two causes of this:

  • when the cursor moves fast and goes ahead of the handle until the handle "catches up" (or when "fluid qml" is too fluid) - this is particularly nasty as the cursor shape rapidly changes and blinks

  • when the cursor moves outside of the allowed degree of freedom for the handle

I looked up the doc but it doesn't seem to contain anything about locking the cursor until the press is released.

I did manage to find a hack to fix it - using a dummy overlay MouseArea with acceptedButtons: Qt.NoButton - this actually helps to fake cursor consistency, but comes with an issue of its own. Having that overlay mouse area doesn't allow the cursor to change to a resize shape when it is over the handle, since the handle is under the overlay mouse area it doesn't get to modify the cursor shape at all. So the resize shape kicks in only after the handle is clicked, which is far from ideal. Setting the overlay mouse area to enabled: false doesn't change that - it still keeps blocking cursor shape changes from underlying mouse areas. There is a workaround for that as well, for example setting the overlay mouse area size to 0x0, but it is kind of ugly.

Ideally, the cursor shape should persist until the mouse area is pressed, regardless of whether it is in or outside of its area - after all, the press is not released if you go outside of it, thus the mouse area is still in control and should persist its cursor shape. For example - the window resize handles remain resize shape even if it is moved to resize the window smaller than its minimal size, until the press is released.

To me it seems that there are flaws in the implementation of MouseArea - the cursor shape is not kept while pressed, and the cursor shape is changed even if the mouse area is disabled.

like image 322
dtech Avatar asked Nov 20 '22 16:11

dtech


1 Answers

I didn't find a way to do this out-of-the-box, it is pretty easy to create a helper for this though. On the qml side you can e.g. have:

CursorChanger {
    cursor: Qt.SizeHorCursor
    active: dragArea.containsMouse || dragArea.drag.active
}

On the C++ side you'll need a helper class like this:

class CursorChanger : public QObject
{
    Q_OBJECT

    Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
    Q_PROPERTY(int cursor READ cursor WRITE setCursor NOTIFY cursorChanged)
    
    // ...
}

In the implementation you can use QGuiApplication::setOverrideCursor and QGuiApplication::restoreOverrideCursor to actually set/reset the cursor. Don't forget to also reset in the CursorChanger destructor if active at that point. If you then register the type:

qmlRegisterType<CursorChanger>(uri, 1, 0, "CursorChanger");`

You can use this type from qml.

like image 189
Adversus Avatar answered Nov 22 '22 08:11

Adversus