Merge pull request #4136 from aws-lumberyard-dev/daimini/dpiIssues/floatingWidgetFlickerBetweenScreens
SystemDpi | Moving floating windows close to the edge between screens makes them flicker
This commit is contained in:
@@ -1615,14 +1615,16 @@ namespace AzQtComponents
|
||||
}
|
||||
|
||||
// Handle snapping to the screen edges/other floating windows while dragging
|
||||
QScreen* screen = Utilities::ScreenAtPoint(globalPos);
|
||||
QScreen* screen = QApplication::screenAt(globalPos);
|
||||
|
||||
AdjustForSnapping(placeholder, screen);
|
||||
if (screen)
|
||||
{
|
||||
AdjustForSnapping(placeholder, screen);
|
||||
m_state.setPlaceholder(placeholder, screen);
|
||||
|
||||
m_state.setPlaceholder(placeholder, screen);
|
||||
|
||||
m_ghostWidget->Enable();
|
||||
RepaintFloatingIndicators();
|
||||
m_ghostWidget->Enable();
|
||||
RepaintFloatingIndicators();
|
||||
}
|
||||
}
|
||||
|
||||
return m_dropZoneState.dragging();
|
||||
|
||||
+62
-4
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <AzQtComponents/Components/FancyDockingGhostWidget.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QCloseEvent>
|
||||
#include <QScreen>
|
||||
@@ -47,7 +48,7 @@ namespace AzQtComponents
|
||||
|
||||
void FancyDockingGhostWidget::setPixmap(const QPixmap& pixmap, const QRect& targetRect, QScreen* screen)
|
||||
{
|
||||
const bool needsRepaint = m_pixmap.cacheKey() != pixmap.cacheKey() || m_clipToWidgets;
|
||||
bool needsRepaint = m_pixmap.cacheKey() != pixmap.cacheKey() || m_clipToWidgets;
|
||||
m_pixmap = pixmap;
|
||||
|
||||
if (pixmap.isNull() || targetRect.isNull() || !screen)
|
||||
@@ -76,11 +77,48 @@ namespace AzQtComponents
|
||||
window->setScreen(screen);
|
||||
}
|
||||
|
||||
setGeometry(targetRect);
|
||||
QPoint midPoint = targetRect.topLeft() + QPoint(targetRect.width() / 2, targetRect.height() / 2);
|
||||
QScreen* pointScreen = QApplication::screenAt(midPoint);
|
||||
QRect rect(targetRect);
|
||||
|
||||
// In environments with multiple screens the screen coordinate system may have gaps, especially when different scaling settings
|
||||
// are involved. When that happens, if a widget is moved into the gap it will resize and translate with undefined behavior.
|
||||
// To prevent this, whenever the widget would end up outside screen boundaries, we resize the widget to be twice its
|
||||
// original size so that the center of the widget is back inside the screen boundaries, and set the ghost widget
|
||||
// to paint the widget pixmap at half the previous size to make the process seamless.
|
||||
// This makes the dragging a lot smoother in most situations.
|
||||
PaintMode paintMode = PaintMode::FULL;
|
||||
|
||||
if (!pointScreen || pointScreen != screen)
|
||||
{
|
||||
if (midPoint.x() >= QCursor::pos().x())
|
||||
{
|
||||
rect.setLeft(rect.left() - rect.width());
|
||||
rect.setTop(rect.top() - rect.height());
|
||||
paintMode = PaintMode::BOTTOMRIGHT;
|
||||
}
|
||||
else
|
||||
{
|
||||
rect.setRight(rect.right() + rect.width());
|
||||
rect.setTop(rect.top() - rect.height());
|
||||
paintMode = PaintMode::BOTTOMLEFT;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_paintMode != paintMode)
|
||||
{
|
||||
needsRepaint = true;
|
||||
}
|
||||
|
||||
setGeometry(rect);
|
||||
m_paintMode = paintMode;
|
||||
|
||||
setPixmapVisible(true);
|
||||
if (needsRepaint)
|
||||
{
|
||||
update();
|
||||
// We use repaint instead of update since the latter has a delay of 1 frame,
|
||||
// which would cause the ghost widget to flicker when changing paint mode.
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +173,27 @@ namespace AzQtComponents
|
||||
yOffset = widgetSize.height() - aspectRatioHeight;
|
||||
}
|
||||
|
||||
painter.drawPixmap(QRect(0, yOffset, widgetSize.width(), aspectRatioHeight), m_pixmap);
|
||||
switch (m_paintMode)
|
||||
{
|
||||
case PaintMode::FULL:
|
||||
{
|
||||
painter.drawPixmap(QRect(0, yOffset, widgetSize.width(), aspectRatioHeight), m_pixmap);
|
||||
}
|
||||
break;
|
||||
|
||||
case PaintMode::BOTTOMLEFT:
|
||||
{
|
||||
painter.drawPixmap(QRect(0, (widgetSize.height() + yOffset) / 2, widgetSize.width() / 2, aspectRatioHeight / 2), m_pixmap);
|
||||
}
|
||||
break;
|
||||
|
||||
case PaintMode::BOTTOMRIGHT:
|
||||
{
|
||||
painter.drawPixmap(QRect(widgetSize.width() / 2, (widgetSize.height() + yOffset) / 2, widgetSize.width() / 2, aspectRatioHeight / 2), m_pixmap);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_clipToWidgets)
|
||||
{
|
||||
painter.restore();
|
||||
|
||||
@@ -45,5 +45,15 @@ namespace AzQtComponents
|
||||
QPixmap m_pixmap;
|
||||
bool m_visible = false; // maintain our own flag, so that we're always ready to render ignoring Qt's widget caching system
|
||||
bool m_clipToWidgets = false;
|
||||
|
||||
//! Determines the way the ghost widget pixmap should be painted on the widget.
|
||||
enum class PaintMode
|
||||
{
|
||||
FULL = 0, //!< Paint the pixmap on the full widget
|
||||
BOTTOMLEFT, //!< Paint the pixmap on the bottom left quarter of the widget, halving its size
|
||||
BOTTOMRIGHT //!< Paint the pixmap on the bottom right quarter of the widget, halving its size
|
||||
};
|
||||
|
||||
PaintMode m_paintMode = PaintMode::FULL;
|
||||
};
|
||||
} // namespace AzQtComponents
|
||||
|
||||
Reference in New Issue
Block a user