2.12.2021, 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

Commit 1071efae authored by Artur Grunau's avatar Artur Grunau
Browse files

Fix bugs with the positioning of MDI windows

Previously, when an MDI window was being dragged very fast and its state
changed from docked to floating (or vice versa), it wouldn't be placed
under the cursor, but instead some way behind it (with regards to the
drag direction). This happened because we decided where to place the
window's based on its last position in its previous state. Now we use
the cursor's position to calculate the window's new position, which
fixes the problem.
parent e3289b08
......@@ -63,12 +63,11 @@ namespace campvis {
widget->show();
floatingWindow->deleteLater();
dockedWindow->move(this->mapFromGlobal(newPos));
dockedWindow->grabMouse();
dockedWindow->forceWindowDrag();
}
}
void MdiDockArea::trackMdiSubWindowsPosition(MdiDockedWindow *dockedWindow, const QPoint& newPos) {
void MdiDockArea::trackMdiSubWindowsPosition(MdiDockedWindow *dockedWindow, const QPoint& /*newPos*/) {
const QRect& subWindowGeometry = dockedWindow->frameGeometry();
const QRect& mdiAreaGeometry = contentsRect();
const QRect& intersection = subWindowGeometry & mdiAreaGeometry;
......@@ -85,7 +84,6 @@ namespace campvis {
MdiFloatingWindow* floatingWindow = new MdiFloatingWindow(widget);
floatingWindow->setWindowTitle(dockedWindow->windowTitle());
floatingWindow->move(this->mapToGlobal(newPos));
floatingWindow->show();
floatingWindow->forceWindowDrag();
......
......@@ -31,6 +31,7 @@
#include <QMdiArea>
#include <QMoveEvent>
#include <QStyle>
namespace campvis {
......@@ -40,10 +41,23 @@ namespace campvis {
, _lastMousePos()
{}
void MdiDockedWindow::forceWindowDrag() {
_dragActive = true;
_lastMousePos = QCursor::pos();
const QPoint& mousePos = this->mapToParent(this->mapFromGlobal(_lastMousePos));
int x = mousePos.x() - this->frameSize().width() / 2;
int y = mousePos.y() - this->style()->pixelMetric(QStyle::PM_TitleBarHeight) / 2;
QPoint newPos = QPoint(x, y);
move(newPos);
this->grabMouse();
}
void MdiDockedWindow::stopWindowDrag() {
if (_dragActive) {
_dragActive = false;
releaseMouse();
this->releaseMouse();
}
}
......@@ -61,8 +75,8 @@ namespace campvis {
/*
* Dragging the subwindow upwards out of the MDI area is blocked for 2 reasons:
* - the subwindow can't be detached and focused reliably in such cases, possibly due
* to the main window's title bar being in the way
* - the docked window can't be detached and focused reliably in such cases, possibly
* due to the main window's title bar being in the way
* - that's how moving subwindows in an MDI area works by default
*/
if (newPos.y() < 0) {
......
......@@ -56,6 +56,13 @@ namespace campvis {
*/
explicit MdiDockedWindow(QWidget* parent = 0, Qt::WindowFlags flags = 0);
/**
* Enter the window into forced drag mode.
*
* This method causes the window to grab the mouse input and follow the cursor.
*/
void forceWindowDrag();
/**
* Cancel the dragging of the window.
*
......
......@@ -32,6 +32,7 @@
#include <QMdiArea>
#include <QMoveEvent>
#include <QHBoxLayout>
#include <QStyle>
namespace campvis {
......@@ -39,7 +40,6 @@ namespace campvis {
: QWidget(parent)
, _widget(widget)
, _dragActive(false)
, _lastMousePos()
{
QLayout* layout = new QHBoxLayout();
layout->setContentsMargins(0, 0, 0, 0);
......@@ -51,7 +51,7 @@ namespace campvis {
void MdiFloatingWindow::forceWindowDrag() {
if (!_dragActive && parent() == 0) {
_dragActive = true;
_lastMousePos = QCursor::pos();
this->snapToCursor(QCursor::pos());
grabMouse();
}
}
......@@ -68,11 +68,7 @@ namespace campvis {
}
void MdiFloatingWindow::mouseMoveEvent(QMouseEvent* event) {
const QPoint& mousePos = event->globalPos();
const QPoint& newPos = pos() + (mousePos - _lastMousePos);
move(newPos);
_lastMousePos = mousePos;
this->snapToCursor(event->globalPos());
}
void MdiFloatingWindow::mouseReleaseEvent(QMouseEvent* event) {
......@@ -85,4 +81,11 @@ namespace campvis {
emit s_positionChanged(this, frameGeometry().topLeft());
}
void MdiFloatingWindow::snapToCursor(const QPoint& cursorPos) {
int x = cursorPos.x() - this->frameSize().width() / 2;
int y = cursorPos.y() - this->style()->pixelMetric(QStyle::PM_TitleBarHeight) / 2;
this->move(x, y);
}
}
......@@ -84,7 +84,7 @@ namespace campvis {
*
* \param newPos the window's new position
*/
void s_positionChanged(MdiFloatingWindow *pipelineWidget, const QPoint& newPos);
void s_positionChanged(MdiFloatingWindow* pipelineWidget, const QPoint& newPos);
protected:
/**
......@@ -103,9 +103,13 @@ namespace campvis {
virtual void moveEvent(QMoveEvent* event);
private:
/**
* Moves the window so that its title bar is centered around \p cursorPos.
*/
void snapToCursor(const QPoint& cursorPos);
QWidget* _widget; ///< The widget this window wraps
bool _dragActive; ///< Is the window currently being dragged?
QPoint _lastMousePos; ///< Last reported mouse position
};
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment