2020-03-12 03:53:51 +00:00
|
|
|
#include "qtdisplaywidget.h"
|
2020-04-26 07:23:42 +00:00
|
|
|
#include "common/bitutils.h"
|
2020-03-12 03:53:51 +00:00
|
|
|
#include "qthostinterface.h"
|
|
|
|
#include "qtutils.h"
|
2020-06-29 16:46:57 +00:00
|
|
|
#include <QtCore/QDebug>
|
2020-03-12 03:53:51 +00:00
|
|
|
#include <QtGui/QGuiApplication>
|
|
|
|
#include <QtGui/QKeyEvent>
|
|
|
|
#include <QtGui/QScreen>
|
|
|
|
#include <QtGui/QWindow>
|
2020-03-22 11:50:49 +00:00
|
|
|
#include <QtGui/QWindowStateChangeEvent>
|
2020-03-12 03:53:51 +00:00
|
|
|
#include <cmath>
|
|
|
|
|
2020-06-29 16:46:57 +00:00
|
|
|
#if !defined(WIN32) && !defined(APPLE)
|
|
|
|
#include <qpa/qplatformnativeinterface.h>
|
|
|
|
#endif
|
|
|
|
|
2020-04-22 11:13:51 +00:00
|
|
|
QtDisplayWidget::QtDisplayWidget(QWidget* parent) : QWidget(parent)
|
2020-03-12 03:53:51 +00:00
|
|
|
{
|
|
|
|
// We want a native window for both D3D and OpenGL.
|
2020-03-22 11:25:10 +00:00
|
|
|
setAutoFillBackground(false);
|
2020-03-12 03:53:51 +00:00
|
|
|
setAttribute(Qt::WA_NativeWindow, true);
|
2020-03-22 11:25:10 +00:00
|
|
|
setAttribute(Qt::WA_NoSystemBackground, true);
|
2020-03-12 03:53:51 +00:00
|
|
|
setAttribute(Qt::WA_PaintOnScreen, true);
|
2020-04-22 11:13:51 +00:00
|
|
|
setFocusPolicy(Qt::StrongFocus);
|
2020-04-26 07:36:49 +00:00
|
|
|
setMouseTracking(true);
|
2020-03-12 03:53:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QtDisplayWidget::~QtDisplayWidget() = default;
|
|
|
|
|
2020-04-08 14:14:19 +00:00
|
|
|
qreal QtDisplayWidget::devicePixelRatioFromScreen() const
|
2020-03-12 03:53:51 +00:00
|
|
|
{
|
|
|
|
QScreen* screen_for_ratio;
|
|
|
|
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
|
|
|
screen_for_ratio = windowHandle()->screen();
|
|
|
|
#else
|
|
|
|
screen_for_ratio = screen();
|
|
|
|
#endif
|
|
|
|
if (!screen_for_ratio)
|
|
|
|
screen_for_ratio = QGuiApplication::primaryScreen();
|
|
|
|
|
|
|
|
return screen_for_ratio ? screen_for_ratio->devicePixelRatio() : static_cast<qreal>(1);
|
|
|
|
}
|
|
|
|
|
2020-04-08 14:14:19 +00:00
|
|
|
int QtDisplayWidget::scaledWindowWidth() const
|
2020-03-12 03:53:51 +00:00
|
|
|
{
|
2020-04-08 14:14:19 +00:00
|
|
|
return static_cast<int>(std::ceil(static_cast<qreal>(width()) * devicePixelRatioFromScreen()));
|
2020-03-12 03:53:51 +00:00
|
|
|
}
|
|
|
|
|
2020-04-08 14:14:19 +00:00
|
|
|
int QtDisplayWidget::scaledWindowHeight() const
|
2020-03-12 03:53:51 +00:00
|
|
|
{
|
2020-04-08 14:14:19 +00:00
|
|
|
return static_cast<int>(std::ceil(static_cast<qreal>(height()) * devicePixelRatioFromScreen()));
|
2020-03-12 03:53:51 +00:00
|
|
|
}
|
|
|
|
|
2020-06-29 16:46:57 +00:00
|
|
|
std::optional<WindowInfo> QtDisplayWidget::getWindowInfo() const
|
|
|
|
{
|
|
|
|
WindowInfo wi;
|
|
|
|
|
|
|
|
// Windows and Apple are easy here since there's no display connection.
|
|
|
|
#if defined(WIN32)
|
|
|
|
wi.type = WindowInfo::Type::Win32;
|
|
|
|
wi.window_handle = reinterpret_cast<void*>(winId());
|
|
|
|
#elif defined(__APPLE__)
|
|
|
|
wi.type = WindowInfo::Type::MacOS;
|
|
|
|
wi.window_handle = reinterpret_cast<void*>(winId());
|
|
|
|
#else
|
|
|
|
QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface();
|
|
|
|
const QString platform_name = QGuiApplication::platformName();
|
|
|
|
if (platform_name == QStringLiteral("xcb"))
|
|
|
|
{
|
|
|
|
wi.type = WindowInfo::Type::X11;
|
|
|
|
wi.display_connection = pni->nativeResourceForWindow("display", windowHandle());
|
|
|
|
wi.window_handle = reinterpret_cast<void*>(winId());
|
|
|
|
}
|
|
|
|
else if (platform_name == QStringLiteral("wayland"))
|
|
|
|
{
|
|
|
|
wi.type = WindowInfo::Type::Wayland;
|
|
|
|
wi.display_connection = pni->nativeResourceForWindow("display", windowHandle());
|
|
|
|
wi.window_handle = pni->nativeResourceForWindow("surface", windowHandle());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
qCritical() << "Unknown PNI platform " << platform_name;
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
wi.surface_width = scaledWindowWidth();
|
|
|
|
wi.surface_height = scaledWindowHeight();
|
2020-06-30 14:35:19 +00:00
|
|
|
wi.surface_scale = devicePixelRatioFromScreen();
|
2020-06-29 16:46:57 +00:00
|
|
|
wi.surface_format = WindowInfo::SurfaceFormat::RGB8;
|
|
|
|
|
|
|
|
return wi;
|
|
|
|
}
|
|
|
|
|
2020-03-12 03:53:51 +00:00
|
|
|
QPaintEngine* QtDisplayWidget::paintEngine() const
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool QtDisplayWidget::event(QEvent* event)
|
|
|
|
{
|
|
|
|
switch (event->type())
|
|
|
|
{
|
|
|
|
case QEvent::KeyPress:
|
|
|
|
case QEvent::KeyRelease:
|
|
|
|
{
|
2020-04-26 07:36:49 +00:00
|
|
|
const QKeyEvent* key_event = static_cast<QKeyEvent*>(event);
|
2020-03-12 03:53:51 +00:00
|
|
|
if (!key_event->isAutoRepeat())
|
2020-04-22 11:13:51 +00:00
|
|
|
emit windowKeyEvent(QtUtils::KeyEventToInt(key_event), event->type() == QEvent::KeyPress);
|
2020-03-12 03:53:51 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-04-26 07:36:49 +00:00
|
|
|
case QEvent::MouseMove:
|
|
|
|
{
|
|
|
|
const qreal dpr = devicePixelRatioFromScreen();
|
|
|
|
const QMouseEvent* mouse_event = static_cast<QMouseEvent*>(event);
|
|
|
|
emit windowMouseMoveEvent(static_cast<int>(static_cast<double>(mouse_event->x()) * dpr),
|
|
|
|
static_cast<int>(static_cast<double>(mouse_event->y()) * dpr));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-04-26 07:23:42 +00:00
|
|
|
case QEvent::MouseButtonPress:
|
|
|
|
case QEvent::MouseButtonRelease:
|
|
|
|
{
|
|
|
|
const u32 button_index = CountTrailingZeros(static_cast<u32>(static_cast<const QMouseEvent*>(event)->button()));
|
2020-04-26 07:36:49 +00:00
|
|
|
emit windowMouseButtonEvent(static_cast<int>(button_index + 1u), event->type() == QEvent::MouseButtonPress);
|
2020-04-26 07:23:42 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-03-12 03:53:51 +00:00
|
|
|
case QEvent::Resize:
|
|
|
|
{
|
|
|
|
QWidget::event(event);
|
|
|
|
|
2020-04-08 14:14:19 +00:00
|
|
|
emit windowResizedEvent(scaledWindowWidth(), scaledWindowHeight());
|
2020-03-12 03:53:51 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-04-05 12:58:47 +00:00
|
|
|
case QEvent::Close:
|
|
|
|
{
|
2020-04-22 11:13:51 +00:00
|
|
|
emit windowClosedEvent();
|
2020-04-05 12:58:47 +00:00
|
|
|
QWidget::event(event);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-03-22 11:50:49 +00:00
|
|
|
case QEvent::WindowStateChange:
|
|
|
|
{
|
|
|
|
QWidget::event(event);
|
|
|
|
|
|
|
|
if (static_cast<QWindowStateChangeEvent*>(event)->oldState() & Qt::WindowMinimized)
|
|
|
|
emit windowRestoredEvent();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-03-12 03:53:51 +00:00
|
|
|
default:
|
|
|
|
return QWidget::event(event);
|
|
|
|
}
|
|
|
|
}
|