151 lines
4.5 KiB
C++
151 lines
4.5 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
#include <AzQtComponents/Components/FancyDockingGhostWidget.h>
|
|
|
|
#include <QDebug>
|
|
#include <QCloseEvent>
|
|
#include <QScreen>
|
|
#include <QWindow>
|
|
#include <QMainWindow>
|
|
#include <QRect>
|
|
#include <QPainter>
|
|
#include <AzQtComponents/Utilities/QtWindowUtilities.h>
|
|
|
|
namespace AzQtComponents
|
|
{
|
|
FancyDockingGhostWidget::FancyDockingGhostWidget(QMainWindow* mainWindow, QWidget* parent) :
|
|
QWidget(parent, Qt::WindowFlags(Qt::ToolTip | Qt::BypassWindowManagerHint | Qt::FramelessWindowHint)),
|
|
m_mainWindow(mainWindow)
|
|
{
|
|
setAttribute(Qt::WA_TranslucentBackground);
|
|
setAttribute(Qt::WA_TransparentForMouseEvents);
|
|
setAttribute(Qt::WA_NoSystemBackground);
|
|
setAutoFillBackground(false);
|
|
}
|
|
|
|
FancyDockingGhostWidget::~FancyDockingGhostWidget()
|
|
{
|
|
}
|
|
|
|
void FancyDockingGhostWidget::setPixmapVisible(bool visible)
|
|
{
|
|
if (m_visible != visible)
|
|
{
|
|
m_visible = visible;
|
|
if (visible)
|
|
{
|
|
update();
|
|
}
|
|
}
|
|
}
|
|
|
|
void FancyDockingGhostWidget::setPixmap(const QPixmap& pixmap, const QRect& targetRect, QScreen* screen)
|
|
{
|
|
const bool needsRepaint = m_pixmap.cacheKey() != pixmap.cacheKey() || m_clipToWidgets;
|
|
m_pixmap = pixmap;
|
|
|
|
if (pixmap.isNull() || targetRect.isNull() || !screen)
|
|
{
|
|
setPixmapVisible(false);
|
|
return;
|
|
}
|
|
|
|
QWindow *window = windowHandle();
|
|
if (!window)
|
|
{
|
|
// So we don't crash when setting a pixmap before having a window
|
|
create();
|
|
window = windowHandle();
|
|
}
|
|
|
|
if (window->screen() != screen)
|
|
{
|
|
// Qt usually handles screens with different scale factors correctly, however
|
|
// when the geometry's origin is in a gap between monitors it won't map to native
|
|
// coordinates correctly, we have to set the screen before setting geometry, so that
|
|
// Qt uses the correct scale factor when mapping to native coordinates.
|
|
// (By gap we mean that monitors are not consecutive, they might be consecutive
|
|
// in native coordinates, but due to using scale factors there will be gaps that don't
|
|
// belong to any screen.
|
|
window->setScreen(screen);
|
|
}
|
|
|
|
setGeometry(targetRect);
|
|
setPixmapVisible(true);
|
|
if (needsRepaint)
|
|
{
|
|
update();
|
|
}
|
|
}
|
|
|
|
// The equivalent of lowering the pixmap under the parent's dock widgets
|
|
void FancyDockingGhostWidget::EnableClippingToDockWidgets()
|
|
{
|
|
if (!m_clipToWidgets)
|
|
{
|
|
m_clipToWidgets = true;
|
|
update();
|
|
}
|
|
}
|
|
|
|
// The equivalent of raising above all of the parent's dock widgets
|
|
void FancyDockingGhostWidget::DisableClippingToDockWidgets()
|
|
{
|
|
if (m_clipToWidgets)
|
|
{
|
|
m_clipToWidgets = false;
|
|
update();
|
|
}
|
|
}
|
|
|
|
void FancyDockingGhostWidget::closeEvent(QCloseEvent* ev)
|
|
{
|
|
ev->ignore(); // Don't close the window.
|
|
}
|
|
|
|
void FancyDockingGhostWidget::paintEvent(QPaintEvent* /* ev */)
|
|
{
|
|
QPainter painter(this);
|
|
|
|
if (m_visible && !m_pixmap.isNull())
|
|
{
|
|
if (m_clipToWidgets)
|
|
{
|
|
painter.save();
|
|
AzQtComponents::SetClipRegionForDockingWidgets(this, painter, m_mainWindow);
|
|
}
|
|
|
|
// Our rendered pixmaps might be smaller than the widget size
|
|
// We put them at the bottom of the widget.
|
|
// It's specifically because we use this widget to render
|
|
// floating dock widgets, and they often render without the titlebar
|
|
// but the geometry of the widget will take the title bar into account.
|
|
QSize widgetSize = rect().size();
|
|
int aspectRatioHeight = (m_pixmap.height() * widgetSize.width()) / m_pixmap.width();
|
|
int yOffset = 0;
|
|
|
|
if (aspectRatioHeight < widgetSize.height())
|
|
{
|
|
yOffset = widgetSize.height() - aspectRatioHeight;
|
|
}
|
|
|
|
painter.drawPixmap(QRect(0, yOffset, widgetSize.width(), aspectRatioHeight), m_pixmap);
|
|
if (m_clipToWidgets)
|
|
{
|
|
painter.restore();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// fill to blank, in case anything is cached
|
|
painter.fillRect(rect(), QColor(0, 0, 0, 0));
|
|
}
|
|
}
|
|
}
|
|
|