Dragging a Titleless Window



  • Hi,

    is it somehow possible to drag a window with Qt::FramelessWindowHint flag using only QML/JS?
    In WPF it was only one line of code: MouseDown += delegate { DragMove(); };
    Just don't know how to get the same behaviour in QML.



  • I don't think so, no.



  • Ok...
    I've tried to expose my QmlApplicationViewer object to QML:
    @QmlApplicationViewer viewer;
    ...
    viewer.rootContext()->setContextProperty("mainwindow", &viewer);
    @

    QmlApplicationViewer is derived from QWidget and has "pos" property:
    Q_PROPERTY(QPoint pos READ pos WRITE move DESIGNABLE false STORED false)

    then I tried to test this approach like this:
    @TitleBar { id: titleBar; width: parent.width; height: 40; opacity: 0.9
    MouseArea {
    id: mouseRegion
    anchors.fill: parent;
    onClicked: {
    console.log("mainwindow.pos");
    mainwindow.pos.x = 0;
    mainwindow.pos.y = 0;
    }
    }
    }
    @
    and to my surprise the window changes its position only in y direction!
    So every time when I click on TitleBar the window jumps to the top side of desktop but not to the lefttop corner!



  • Hmmm I was playing around with the difference between ; and , in the onClicked stuff the other day and did find that things didn't always act the same. Just for giggles maybe try

    @onClicked: { mainwindow.pos.x = 0, mainwindow.pos.y = 0, console.log("mainwindow.pos") }@

    I know it seems terribly small like it shouldn't do anything, and it might not. But hey it never hurts to try.


  • Moderators

    Javascript says they should behave differently:-) So why is it surprising that they do?



  • To tell the truth - I'm not familiar with Javascript. For me it looks like a function body and when the first and the last lines are working as supposed and the middle is not - it is somehow strange...

    but anyway it is working like a charm now:
    @TitleBar { id: titleBar; width: parent.width; height: 40; opacity: 0.9
    MouseArea {
    id: mouseRegion
    anchors.fill: parent;
    property variant clickPos: "1,1"
    onPressed: {
    clickPos = Qt.point(mouse.x,mouse.y)
    }
    onPositionChanged: {
    var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
    mainwindow.pos = Qt.point(mainwindow.pos.x+delta.x,
    mainwindow.pos.y+delta.y)
    //console.log(mouse.x-clickPos.x,mouse.y-clickPos.y)
    }
    }
    }@



  • I tried to implement your solution to my app but it's not working for me...
    I'm using QtQuick2 which use QtQuick2ApplicationViewer instead of QmlApplicationViewer.

    When I trying to drag window I get this:
    @TypeError: Cannot read property 'x' of undefined@

    basically QtQuick2ApplicationViewer do not have ".pos" property
    Any idea how to overcome this issue ?



  • Well it's not very elegant or very advisable I suppose but this seems to work:

    @
    import QtQuick 2.1
    import QtQuick.Window 2.0

    Window {
    id: window
    visible: true
    width: 100
    height: 100
    flags: Qt.FramelessWindowHint

    Rectangle {
        color: "steelblue"
        anchors.top: parent.top
        width: parent.width
        height: 20
        MouseArea {
            anchors.fill: parent
            property real lastMouseX: 0
            property real lastMouseY: 0
            onPressed: {
                lastMouseX = mouseX
                lastMouseY = mouseY
            }
            onMouseXChanged: window.x += (mouseX - lastMouseX)
            onMouseYChanged: window.y += (mouseY - lastMouseY)
        }
    }
    

    }
    @



  • Why isn't it very elegant or advisable? Is there another way?
    Thanks

    [quote author="ecloud" date="1380629763"]Well it's not very elegant or very advisable I suppose but this seems to work:

    @
    import QtQuick 2.1
    import QtQuick.Window 2.0

    Window {
    id: window
    visible: true
    width: 100
    height: 100
    flags: Qt.FramelessWindowHint

    Rectangle {
        color: "steelblue"
        anchors.top: parent.top
        width: parent.width
        height: 20
        MouseArea {
            anchors.fill: parent
            property real lastMouseX: 0
            property real lastMouseY: 0
            onPressed: {
                lastMouseX = mouseX
                lastMouseY = mouseY
            }
            onMouseXChanged: window.x += (mouseX - lastMouseX)
            onMouseYChanged: window.y += (mouseY - lastMouseY)
        }
    }
    

    }
    @[/quote]



  • Hello and welcome to devnet ricardodovalle,

    [quote author="ricardodovalle" date="1395367064"]Why isn't it very elegant or advisable? Is there another way?
    Thanks[/quote]

    It is not elegant because the position is calculated on mouse move. It requires 2 more Components and 3 notifications/signals. It's a workaround, but there is currently no possibility of dragging the Window using the Drag of the MouseArea, so this might work out well.



  • Thanks

    [quote author="onek24" date="1395392141"]Hello and welcome to devnet ricardodovalle,

    It is not elegant because the position is calculated on mouse move. It requires 2 more Components and 3 notifications/signals. It's a workaround, but there is currently no possibility of dragging the *Window using the Drag of the MouseArea, so this might work out well.

    [/quote]

    onek24



  • Sadly, this solution really doesn't work well for me on Ubuntu, dragging the window too fast make it jiggle a lot along the way, it's weird.



  • Yes I noticed the flicker issue. I managed to solve it by piping the global cursor position into the QML code. There is a race condition with the MouseArea relative position. Details at http://subgroup-ash.blogspot.de/2015/12/qt-issue-problem-with-frameless-window.html



  • Anyone has more elegant solution now? Why doesn't Qt make frameless window movable by default?



  • I suppose that it isn't up to Qt to make a frameless window moveable.

    The documentation says:
    Qt::FramelessWindowHint: Produces a borderless window. The user cannot move or resize a borderless window via the window system. On X11, the result of the flag is dependent on the window manager and its ability to understand Motif and/or NETWM hints. Most existing modern window managers can handle this.

    It seems to be up to the window manager to handle the FramelessWindowHint, as it is also the window manager who will provide a window for your application and which takes care of the moving an resizing.



  • I don't know anybody will find this solution "elegant" but this one is short, easy to read and works:

    Window {
      MouseArea {
            hoverEnabled: true
            anchors.fill: parent
            property real anchorX
            property real anchorY
            onPressed: { anchorX = mouse.x; anchorY = mouse.y }
            onMouseXChanged: if (pressed) parent.x += mouse.x-anchorX
            onMouseYChanged: if (pressed) parent.y += mouse.y-anchorY
      }
    }
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.