Separate application into platform specific files. (#4799)

Signed-off-by: Yaakuro <y1@codeposer.net>
monroegm-disable-blank-issue-2
Yaakuro 4 years ago committed by GitHub
parent b536abbf4e
commit 8e03d6f306
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -16,18 +16,11 @@
#include <QScopedValueRollback> #include <QScopedValueRollback>
#include <QToolBar> #include <QToolBar>
#include <QLoggingCategory> #include <QLoggingCategory>
#if defined(AZ_PLATFORM_WINDOWS)
#include <QtGui/qpa/qplatformnativeinterface.h>
#include <QtGui/private/qhighdpiscaling_p.h>
#endif
#include <AzCore/Component/ComponentApplication.h> #include <AzCore/Component/ComponentApplication.h>
#include <AzCore/IO/Path/Path.h> #include <AzCore/IO/Path/Path.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h> #include <AzCore/Settings/SettingsRegistryMergeUtils.h>
// AzFramework
#if defined(AZ_PLATFORM_WINDOWS)
# include <AzFramework/Input/Buses/Notifications/RawInputNotificationBus_Platform.h>
#endif // defined(AZ_PLATFORM_WINDOWS)
// AzQtComponents // AzQtComponents
#include <AzQtComponents/Components/GlobalEventFilter.h> #include <AzQtComponents/Components/GlobalEventFilter.h>
@ -39,7 +32,6 @@
#include "Settings.h" #include "Settings.h"
#include "CryEdit.h" #include "CryEdit.h"
enum enum
{ {
// in milliseconds // in milliseconds
@ -241,7 +233,6 @@ namespace Editor
EditorQtApplication::EditorQtApplication(int& argc, char** argv) EditorQtApplication::EditorQtApplication(int& argc, char** argv)
: AzQtApplication(argc, argv) : AzQtApplication(argc, argv)
, m_inWinEventFilter(false)
, m_stylesheet(new AzQtComponents::O3DEStylesheet(this)) , m_stylesheet(new AzQtComponents::O3DEStylesheet(this))
, m_idleTimer(new QTimer(this)) , m_idleTimer(new QTimer(this))
{ {
@ -368,86 +359,10 @@ namespace Editor
UninstallEditorTranslators(); UninstallEditorTranslators();
} }
#if defined(AZ_PLATFORM_WINDOWS) EditorQtApplication* EditorQtApplication::instance()
bool EditorQtApplication::nativeEventFilter([[maybe_unused]] const QByteArray& eventType, void* message, long* result)
{ {
MSG* msg = (MSG*)message; return static_cast<EditorQtApplication*>(QApplication::instance());
if (msg->message == WM_MOVING || msg->message == WM_SIZING)
{
m_isMovingOrResizing = true;
}
else if (msg->message == WM_EXITSIZEMOVE)
{
m_isMovingOrResizing = false;
}
// Prevent the user from being able to move the window in game mode.
// This is done during the hit test phase to bypass the native window move messages. If the window
// decoration wrapper title bar contains the cursor, set the result to HTCLIENT instead of
// HTCAPTION.
if (msg->message == WM_NCHITTEST && GetIEditor()->IsInGameMode())
{
const LRESULT defWinProcResult = DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
if (defWinProcResult == 1)
{
if (QWidget* widget = QWidget::find((WId)msg->hwnd))
{
if (auto wrapper = qobject_cast<const AzQtComponents::WindowDecorationWrapper *>(widget))
{
AzQtComponents::TitleBar* titleBar = wrapper->titleBar();
const short global_x = static_cast<short>(LOWORD(msg->lParam));
const short global_y = static_cast<short>(HIWORD(msg->lParam));
const QPoint globalPos = QHighDpi::fromNativePixels(QPoint(global_x, global_y), widget->window()->windowHandle());
const QPoint local = titleBar->mapFromGlobal(globalPos);
if (titleBar->draggableRect().contains(local) && !titleBar->isTopResizeArea(globalPos))
{
*result = HTCLIENT;
return true;
}
}
}
}
}
// Ensure that the Windows WM_INPUT messages get passed through to the AzFramework input system.
// These events are only broadcast in game mode. In Editor mode, RenderViewportWidget creates synthetic
// keyboard and mouse events via Qt.
if (GetIEditor()->IsInGameMode())
{
if (msg->message == WM_INPUT)
{
UINT rawInputSize;
const UINT rawInputHeaderSize = sizeof(RAWINPUTHEADER);
GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, nullptr, &rawInputSize, rawInputHeaderSize);
AZStd::array<BYTE, sizeof(RAWINPUT)> rawInputBytesArray;
LPBYTE rawInputBytes = rawInputBytesArray.data();
[[maybe_unused]] const UINT bytesCopied = GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, rawInputBytes, &rawInputSize, rawInputHeaderSize);
CRY_ASSERT(bytesCopied == rawInputSize);
RAWINPUT* rawInput = (RAWINPUT*)rawInputBytes;
CRY_ASSERT(rawInput);
AzFramework::RawInputNotificationBusWindows::Broadcast(&AzFramework::RawInputNotificationsWindows::OnRawInputEvent, *rawInput);
return false;
}
else if (msg->message == WM_DEVICECHANGE)
{
if (msg->wParam == 0x0007) // DBT_DEVNODES_CHANGED
{
AzFramework::RawInputNotificationBusWindows::Broadcast(&AzFramework::RawInputNotificationsWindows::OnRawInputDeviceChangeEvent);
}
return true;
}
}
return false;
} }
#endif
void EditorQtApplication::OnEditorNotifyEvent(EEditorNotifyEvent event) void EditorQtApplication::OnEditorNotifyEvent(EEditorNotifyEvent event)
{ {
@ -505,11 +420,6 @@ namespace Editor
return m_stylesheet->GetColorByName(name); return m_stylesheet->GetColorByName(name);
} }
EditorQtApplication* EditorQtApplication::instance()
{
return static_cast<EditorQtApplication*>(QApplication::instance());
}
bool EditorQtApplication::IsActive() bool EditorQtApplication::IsActive()
{ {
return applicationState() == Qt::ApplicationActive; return applicationState() == Qt::ApplicationActive;
@ -613,42 +523,6 @@ namespace Editor
case QEvent::KeyRelease: case QEvent::KeyRelease:
m_pressedKeys.remove(reinterpret_cast<QKeyEvent*>(event)->key()); m_pressedKeys.remove(reinterpret_cast<QKeyEvent*>(event)->key());
break; break;
#ifdef AZ_PLATFORM_WINDOWS
case QEvent::Leave:
{
// if we receive a leave event for a toolbar on Windows
// check first whether we really left it. If we didn't: start checking
// for the tool bar under the mouse by timer to check when we really left.
// Synthesize a new leave event then. Workaround for LY-69788
auto toolBarAt = [](const QPoint& pos) -> QToolBar* {
QWidget* widget = qApp->widgetAt(pos);
while (widget != nullptr)
{
if (QToolBar* tb = qobject_cast<QToolBar*>(widget))
{
return tb;
}
widget = widget->parentWidget();
}
return nullptr;
};
if (object == toolBarAt(QCursor::pos()))
{
QTimer* t = new QTimer(object);
t->start(100);
connect(t, &QTimer::timeout, object, [t, object, toolBarAt]() {
if (object != toolBarAt(QCursor::pos()))
{
QEvent event(QEvent::Leave);
qApp->sendEvent(object, &event);
t->deleteLater();
}
});
return true;
}
break;
}
#endif
default: default:
break; break;
} }

@ -72,14 +72,12 @@ namespace Editor
//// ////
static EditorQtApplication* instance(); static EditorQtApplication* instance();
static EditorQtApplication* newInstance(int& argc, char** argv);
static bool IsActive(); static bool IsActive();
bool isMovingOrResizing() const; bool isMovingOrResizing() const;
// QAbstractNativeEventFilter:
bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override;
// IEditorNotifyListener: // IEditorNotifyListener:
void OnEditorNotifyEvent(EEditorNotifyEvent event) override; void OnEditorNotifyEvent(EEditorNotifyEvent event) override;
@ -100,6 +98,10 @@ namespace Editor
signals: signals:
void skinChanged(); void skinChanged();
protected:
bool m_isMovingOrResizing = false;
private: private:
enum TimerResetFlag enum TimerResetFlag
{ {
@ -116,8 +118,6 @@ namespace Editor
AzQtComponents::O3DEStylesheet* m_stylesheet; AzQtComponents::O3DEStylesheet* m_stylesheet;
bool m_inWinEventFilter = false;
// Translators // Translators
void InstallEditorTranslators(); void InstallEditorTranslators();
void UninstallEditorTranslators(); void UninstallEditorTranslators();
@ -127,7 +127,6 @@ namespace Editor
QTranslator* m_editorTranslator = nullptr; QTranslator* m_editorTranslator = nullptr;
QTranslator* m_assetBrowserTranslator = nullptr; QTranslator* m_assetBrowserTranslator = nullptr;
QTimer* const m_idleTimer = nullptr; QTimer* const m_idleTimer = nullptr;
bool m_isMovingOrResizing = false;
AZ::UserSettingsProvider m_localUserSettings; AZ::UserSettingsProvider m_localUserSettings;

@ -4135,9 +4135,9 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[])
Editor::EditorQtApplication::InstallQtLogHandler(); Editor::EditorQtApplication::InstallQtLogHandler();
AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware); AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware);
Editor::EditorQtApplication app(argc, argv); Editor::EditorQtApplication* app = Editor::EditorQtApplication::newInstance(argc, argv);
if (app.arguments().contains("-autotest_mode")) if (app->arguments().contains("-autotest_mode"))
{ {
// Nullroute all stdout to null for automated tests, this way we make sure // Nullroute all stdout to null for automated tests, this way we make sure
// that the test result output is not polluted with unrelated output data. // that the test result output is not polluted with unrelated output data.
@ -4173,12 +4173,7 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[])
return -1; return -1;
} }
AzToolsFramework::EditorEvents::Bus::Broadcast(&AzToolsFramework::EditorEvents::NotifyQtApplicationAvailable, &app); AzToolsFramework::EditorEvents::Bus::Broadcast(&AzToolsFramework::EditorEvents::NotifyQtApplicationAvailable, app);
#if defined(AZ_PLATFORM_MAC)
// Native menu bars do not work on macOS due to all the tool dialogs
QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
#endif
int exitCode = 0; int exitCode = 0;
@ -4189,9 +4184,9 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[])
if (didCryEditStart) if (didCryEditStart)
{ {
app.EnableOnIdle(); app->EnableOnIdle();
ret = app.exec(); ret = app->exec();
} }
else else
{ {
@ -4202,6 +4197,8 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[])
} }
delete app;
gSettings.Disconnect(); gSettings.Disconnect();
return ret; return ret;

@ -6,7 +6,7 @@
* *
*/ */
#include "QtEditorApplication.h" #include "QtEditorApplication_linux.h"
#ifdef PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB #ifdef PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
#include <AzFramework/XcbEventHandler.h> #include <AzFramework/XcbEventHandler.h>
@ -14,7 +14,16 @@
namespace Editor namespace Editor
{ {
bool EditorQtApplication::nativeEventFilter([[maybe_unused]] const QByteArray& eventType, void* message, long*) EditorQtApplication* EditorQtApplication::newInstance(int& argc, char** argv)
{
#ifdef PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
return new EditorQtApplicationXcb(argc, argv);
#endif
return nullptr;
}
bool EditorQtApplicationXcb::nativeEventFilter([[maybe_unused]] const QByteArray& eventType, void* message, long*)
{ {
if (GetIEditor()->IsInGameMode()) if (GetIEditor()->IsInGameMode())
{ {

@ -0,0 +1,25 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <Editor/Core/QtEditorApplication.h>
namespace Editor
{
class EditorQtApplicationXcb : public EditorQtApplication
{
Q_OBJECT
public:
EditorQtApplicationXcb(int& argc, char** argv)
: EditorQtApplication(argc, argv)
{
}
// QAbstractNativeEventFilter:
bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override;
};
} // namespace Editor

@ -7,6 +7,6 @@
# #
set(FILES set(FILES
../../Core/QtEditorApplication_linux.cpp Editor/Core/QtEditorApplication_linux.cpp
../Common/Unimplemented/Util/Mailer_Unimplemented.cpp ../Common/Unimplemented/Util/Mailer_Unimplemented.cpp
) )

@ -0,0 +1,25 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <Editor/Core/QtEditorApplication.h>
namespace Editor
{
class EditorQtApplicationMac : public EditorQtApplication
{
Q_OBJECT
public:
EditorQtApplicationMac(int& argc, char** argv)
: EditorQtApplication(argc, argv)
{
}
// QAbstractNativeEventFilter:
bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override;
};
} // namespace Editor

@ -19,7 +19,14 @@
namespace Editor namespace Editor
{ {
bool EditorQtApplication::nativeEventFilter(const QByteArray& eventType, void* message, long* result) EditorQtApplication* EditorQtApplication::newInstance(int& argc, char** argv)
{
QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
return new EditorQtApplicationMac(argc, argv);
}
bool EditorQtApplicationMac::nativeEventFilter(const QByteArray& eventType, void* message, long* result)
{ {
NSEvent* event = (NSEvent*)message; NSEvent* event = (NSEvent*)message;
if (GetIEditor()->IsInGameMode()) if (GetIEditor()->IsInGameMode())

@ -7,7 +7,7 @@
# #
set(FILES set(FILES
../../Core/QtEditorApplication_mac.mm Editor/Core/QtEditorApplication_mac.mm
../../LogFile_mac.mm ../../LogFile_mac.mm
../../WindowObserver_mac.h ../../WindowObserver_mac.h
../../WindowObserver_mac.mm ../../WindowObserver_mac.mm

@ -0,0 +1,165 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include "QtEditorApplication_windows.h"
// Qt
#include <QAbstractEventDispatcher>
#include <QScopedValueRollback>
#include <QToolBar>
#include <QLoggingCategory>
#include <QTimer>
#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtGui/qpa/qplatformnativeinterface.h>
// AzQtComponents
#include <AzQtComponents/Components/Titlebar.h>
#include <AzQtComponents/Components/WindowDecorationWrapper.h>
// AzFramework
#include <AzFramework/Input/Buses/Notifications/RawInputNotificationBus_Platform.h>
namespace Editor
{
EditorQtApplication* EditorQtApplication::newInstance(int& argc, char** argv)
{
return new EditorQtApplicationWindows(argc, argv);
}
bool EditorQtApplicationWindows::nativeEventFilter([[maybe_unused]] const QByteArray& eventType, void* message, long* result)
{
MSG* msg = (MSG*)message;
if (msg->message == WM_MOVING || msg->message == WM_SIZING)
{
m_isMovingOrResizing = true;
}
else if (msg->message == WM_EXITSIZEMOVE)
{
m_isMovingOrResizing = false;
}
// Prevent the user from being able to move the window in game mode.
// This is done during the hit test phase to bypass the native window move messages. If the window
// decoration wrapper title bar contains the cursor, set the result to HTCLIENT instead of
// HTCAPTION.
if (msg->message == WM_NCHITTEST && GetIEditor()->IsInGameMode())
{
const LRESULT defWinProcResult = DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
if (defWinProcResult == 1)
{
if (QWidget* widget = QWidget::find((WId)msg->hwnd))
{
if (auto wrapper = qobject_cast<const AzQtComponents::WindowDecorationWrapper*>(widget))
{
AzQtComponents::TitleBar* titleBar = wrapper->titleBar();
const short global_x = static_cast<short>(LOWORD(msg->lParam));
const short global_y = static_cast<short>(HIWORD(msg->lParam));
const QPoint globalPos = QHighDpi::fromNativePixels(QPoint(global_x, global_y), widget->window()->windowHandle());
const QPoint local = titleBar->mapFromGlobal(globalPos);
if (titleBar->draggableRect().contains(local) && !titleBar->isTopResizeArea(globalPos))
{
*result = HTCLIENT;
return true;
}
}
}
}
}
// Ensure that the Windows WM_INPUT messages get passed through to the AzFramework input system.
// These events are only broadcast in game mode. In Editor mode, RenderViewportWidget creates synthetic
// keyboard and mouse events via Qt.
if (GetIEditor()->IsInGameMode())
{
if (msg->message == WM_INPUT)
{
UINT rawInputSize;
const UINT rawInputHeaderSize = sizeof(RAWINPUTHEADER);
GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, nullptr, &rawInputSize, rawInputHeaderSize);
AZStd::array<BYTE, sizeof(RAWINPUT)> rawInputBytesArray;
LPBYTE rawInputBytes = rawInputBytesArray.data();
[[maybe_unused]] const UINT bytesCopied =
GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, rawInputBytes, &rawInputSize, rawInputHeaderSize);
CRY_ASSERT(bytesCopied == rawInputSize);
RAWINPUT* rawInput = (RAWINPUT*)rawInputBytes;
CRY_ASSERT(rawInput);
AzFramework::RawInputNotificationBusWindows::Broadcast(
&AzFramework::RawInputNotificationsWindows::OnRawInputEvent, *rawInput);
return false;
}
else if (msg->message == WM_DEVICECHANGE)
{
if (msg->wParam == 0x0007) // DBT_DEVNODES_CHANGED
{
AzFramework::RawInputNotificationBusWindows::Broadcast(
&AzFramework::RawInputNotificationsWindows::OnRawInputDeviceChangeEvent);
}
return true;
}
}
return false;
}
bool EditorQtApplicationWindows::eventFilter(QObject* object, QEvent* event)
{
switch (event->type())
{
case QEvent::Leave:
{
// if we receive a leave event for a toolbar on Windows
// check first whether we really left it. If we didn't: start checking
// for the tool bar under the mouse by timer to check when we really left.
// Synthesize a new leave event then. Workaround for LY-69788
auto toolBarAt = [](const QPoint& pos) -> QToolBar*
{
QWidget* widget = qApp->widgetAt(pos);
while (widget != nullptr)
{
if (QToolBar* tb = qobject_cast<QToolBar*>(widget))
{
return tb;
}
widget = widget->parentWidget();
}
return false;
};
if (object == toolBarAt(QCursor::pos()))
{
QTimer* t = new QTimer(object);
t->start(100);
connect(
t, &QTimer::timeout, object,
[t, object, toolBarAt]()
{
if (object != toolBarAt(QCursor::pos()))
{
QEvent event(QEvent::Leave);
qApp->sendEvent(object, &event);
t->deleteLater();
}
});
return true;
}
break;
}
default:
break;
}
return EditorQtApplication::eventFilter(object, event);
}
} // namespace Editor

@ -0,0 +1,27 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <Editor/Core/QtEditorApplication.h>
namespace Editor
{
class EditorQtApplicationWindows : public EditorQtApplication
{
Q_OBJECT
public:
EditorQtApplicationWindows(int& argc, char** argv)
: EditorQtApplication(argc, argv)
{
}
// QAbstractNativeEventFilter:
bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override;
bool eventFilter(QObject* object, QEvent* event) override;
};
} // namespace Editor

@ -7,5 +7,6 @@
# #
set(FILES set(FILES
Editor/Core/QtEditorApplication_windows.cpp
Util/Mailer_Windows.cpp Util/Mailer_Windows.cpp
) )

Loading…
Cancel
Save