I got inspired by this code https://github.com/wbt729/quickdock and extending it to make it work like native windows docking functionality like in Visual studio , where the user can grab the title bar and drag the window to mouse cursor.
I can drag and undock the window fine but it does not drag it to mouse cursor when initially moved
here is the example of the code :
import QtQuick
import QtQuick.Controls
import QtQuick.Window
import QtQuick.Controls.Material
Item {
id: root
default property alias contents: placeholder.data
property alias title: titleLabel.text
implicitHeight: mainWindow.height - statusBar.height - 15
Rectangle {
id: content
anchors.fill: parent
height: implicitHeight
state: "docked"
border.color: "slategrey"
border.width: 1
ToolBar {
id: toolBar
implicitHeight: 30
Material.foreground: "white"
Material.background: "#dcdcdc"
anchors { top: parent.top; left: parent.left; right: parent.right }
Label {
id: titleLabel
color: "black"
anchors { left: parent.left; leftMargin: 8; verticalCenter: parent.verticalCenter }
}
MouseArea {
id: dragMouseArea
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
property variant clickPos: "0,0"
onPressed: (mouse) => {
clickPos = Qt.point(mouse.x,mouse.y)
if (content.state === "docked") {
// Set the initial position of the window when undocked
window.x = mouse.x
window.y = mouse.y
}
}
onPositionChanged: (mouse) => {
var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
var new_x = window.x + delta.x
var new_y = window.y + delta.y
if (content.state === "docked") {
// Check if the mouse is outside the bounds of the docked area
if (mouse.y < toolBar.height || mouse.x < 0 || mouse.x > parent.width) {
content.state = "undocked"
// Move the window to the mouse position
window.x = new_x
window.y = new_y
}
} else {
// Get the maximum x and y positions for the undocked window
var max_x = Screen.desktopAvailableWidth - window.width
var max_y = Screen.desktopAvailableHeight - window.height
// Update the window position, making sure it stays within the screen bounds
if (new_x < 0) new_x = 0
if (new_x > max_x) new_x = max_x
if (new_y < 0) new_y = 0
if (new_y > max_y) new_y = max_y
window.x = new_x
window.y = new_y
}
}
onClicked: {
if (mouse.button === Qt.RightButton)
contextMenu.popup()
}
Menu {
id: contextMenu
MenuItem { id: dockMenu; text: "Dock"; onClicked: content.state = "docked"; implicitHeight: 30}
MenuItem { id: unDockMenu; text: "Float"; onClicked: content.state = "undocked" ; implicitHeight: 30}
}
}
}
Item {
id: placeholder
anchors { top: toolBar.bottom; left: parent.left; right: parent.right; bottom: parent.bottom }
}
states: [
State {
name: "undocked"
PropertyChanges { target: root; height: 0 }
PropertyChanges { target: window; visible: true }
ParentChange { target: content; parent: undockedContainer }
//PropertyChanges { target: window; visible: true; x: 250; y: 250 }
//this is to make sure the width becomes zero and rest of the control takes the realstate
PropertyChanges {target: navigationWindow; width: 0 }
PropertyChanges {target: toolBar; Material.background: "#f0e68c" }
PropertyChanges {target: unDockMenu; enabled: false }
PropertyChanges {target: dockMenu; enabled: true }
},
State {
name: "docked"
PropertyChanges { target: root; height: implicitHeight }
PropertyChanges { target: window; visible: false }
ParentChange { target: content; parent: root }
PropertyChanges {target: unDockMenu; enabled: true }
PropertyChanges {target: dockMenu; enabled: false }
}
]
}
Window {
id: window
width: 250;
height: 700;
flags: Qt.Window | Qt.CustomizeWindowHint
Item {
id: undockedContainer
anchors.fill: parent
}
onClosing: {
content.state = "docked"
}
}
}
Here one aproach to solve your positioning problem. Remove the onPress function and change the onPositionChanged function to this:
See the comments for more details.