From f5effaabcccefc138aa29f018ea2cc2b04e90b57 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Fri, 17 Sep 2021 16:43:42 -0700 Subject: [PATCH] Consolidate all xcb functionality into one subdirectory The Linux platform has multiple windowing systems. Support for xcb is currently in progress, support for Wayland is planned in the future. The way the current xcb support is included is by making some file with a `_xcb` suffix, and placing `#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB` around most of that file's contents. With this change, all of the code in AzFramework that uses xcb directly is inside the `Platform/Common/Xcb` subdirectory. It greatly reduces the amount of code in compile-time `#ifdef` checks for the chosen windowing system. It also provides a logical place to include O3DE-specific xcb C++ wrappers and interfaces, without polluting non-xcb related code. Signed-off-by: Chris Burel --- .../Editor/Core/QtEditorApplication_linux.cpp | 4 +- Code/Framework/AzFramework/CMakeLists.txt | 2 +- .../Common/Xcb/AzFramework/XcbApplication.cpp | 45 +- .../Common/Xcb/AzFramework/XcbApplication.h | 20 +- .../Xcb/AzFramework/XcbConnectionManager.h | 42 ++ .../Common/Xcb/AzFramework/XcbEventHandler.h | 40 ++ .../AzFramework/XcbInputDeviceKeyboard.cpp | 464 +++++++++--------- .../Xcb/AzFramework/XcbInputDeviceKeyboard.h | 46 ++ .../Common/Xcb/AzFramework/XcbInterface.h | 38 ++ .../Xcb/AzFramework/XcbNativeWindow.cpp | 51 +- .../Common/Xcb/AzFramework/XcbNativeWindow.h | 19 +- .../Common/Xcb/azframework_xcb_files.cmake | 18 + .../AzFramework/API/ApplicationAPI_Linux.h | 54 -- .../Application/Application_Linux.cpp | 6 +- .../Keyboard/InputDeviceKeyboard_Linux.cpp | 27 + .../Windowing/NativeWindow_Linux.cpp | 7 +- .../Platform/Linux/platform_linux.cmake | 10 +- .../Platform/Linux/platform_linux_files.cmake | 6 +- .../Platform/Linux/RHI/WSISurface_Linux.cpp | 6 +- 19 files changed, 515 insertions(+), 390 deletions(-) create mode 100644 Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbConnectionManager.h create mode 100644 Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbEventHandler.h create mode 100644 Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInputDeviceKeyboard.h create mode 100644 Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInterface.h create mode 100644 Code/Framework/AzFramework/Platform/Common/Xcb/azframework_xcb_files.cmake create mode 100644 Code/Framework/AzFramework/Platform/Linux/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Linux.cpp diff --git a/Code/Editor/Core/QtEditorApplication_linux.cpp b/Code/Editor/Core/QtEditorApplication_linux.cpp index 175bef0238..2fd4ef629e 100644 --- a/Code/Editor/Core/QtEditorApplication_linux.cpp +++ b/Code/Editor/Core/QtEditorApplication_linux.cpp @@ -9,7 +9,7 @@ #include "QtEditorApplication.h" #ifdef PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB -#include +#include #endif namespace Editor @@ -19,7 +19,7 @@ namespace Editor if (GetIEditor()->IsInGameMode()) { #ifdef PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - AzFramework::LinuxXcbEventHandlerBus::Broadcast(&AzFramework::LinuxXcbEventHandler::HandleXcbEvent, static_cast(message)); + AzFramework::XcbEventHandlerBus::Broadcast(&AzFramework::XcbEventHandler::HandleXcbEvent, static_cast(message)); #endif return true; } diff --git a/Code/Framework/AzFramework/CMakeLists.txt b/Code/Framework/AzFramework/CMakeLists.txt index 6f6e47855e..f6851f0ab8 100644 --- a/Code/Framework/AzFramework/CMakeLists.txt +++ b/Code/Framework/AzFramework/CMakeLists.txt @@ -95,4 +95,4 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) endif() -endif() \ No newline at end of file +endif() diff --git a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbApplication.cpp b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbApplication.cpp index aaab67b2a1..7cbd9ae0e2 100644 --- a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbApplication.cpp +++ b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbApplication.cpp @@ -6,29 +6,26 @@ * */ -#include -#include -#include "Application_Linux_xcb.h" +#include +#include -//////////////////////////////////////////////////////////////////////////////////////////////////// namespace AzFramework { -#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB //////////////////////////////////////////////////////////////////////////////////////////////// - class LinuxXcbConnectionManagerImpl - : public LinuxXcbConnectionManagerBus::Handler + class XcbConnectionManagerImpl + : public XcbConnectionManagerBus::Handler { public: - LinuxXcbConnectionManagerImpl() + XcbConnectionManagerImpl() { m_xcbConnection = xcb_connect(nullptr, nullptr); - AZ_Error("ApplicationLinux", m_xcbConnection != nullptr, "Unable to connect to X11 Server."); - LinuxXcbConnectionManagerBus::Handler::BusConnect(); + AZ_Error("Application", m_xcbConnection != nullptr, "Unable to connect to X11 Server."); + XcbConnectionManagerBus::Handler::BusConnect(); } - ~LinuxXcbConnectionManagerImpl() + ~XcbConnectionManagerImpl() override { - LinuxXcbConnectionManagerBus::Handler::BusDisconnect(); + XcbConnectionManagerBus::Handler::BusDisconnect(); xcb_disconnect(m_xcbConnection); } @@ -42,53 +39,51 @@ namespace AzFramework }; //////////////////////////////////////////////////////////////////////////////////////////////// - ApplicationLinux_xcb::ApplicationLinux_xcb() + XcbApplication::XcbApplication() { LinuxLifecycleEvents::Bus::Handler::BusConnect(); - m_xcbConnectionManager = AZStd::make_unique(); - if (LinuxXcbConnectionManagerInterface::Get() == nullptr) + m_xcbConnectionManager = AZStd::make_unique(); + if (XcbConnectionManagerInterface::Get() == nullptr) { - LinuxXcbConnectionManagerInterface::Register(m_xcbConnectionManager.get()); + XcbConnectionManagerInterface::Register(m_xcbConnectionManager.get()); } } //////////////////////////////////////////////////////////////////////////////////////////////// - ApplicationLinux_xcb::~ApplicationLinux_xcb() + XcbApplication::~XcbApplication() { - if (LinuxXcbConnectionManagerInterface::Get() == m_xcbConnectionManager.get()) + if (XcbConnectionManagerInterface::Get() == m_xcbConnectionManager.get()) { - LinuxXcbConnectionManagerInterface::Unregister(m_xcbConnectionManager.get()); + XcbConnectionManagerInterface::Unregister(m_xcbConnectionManager.get()); } m_xcbConnectionManager.reset(); LinuxLifecycleEvents::Bus::Handler::BusDisconnect(); } //////////////////////////////////////////////////////////////////////////////////////////////// - void ApplicationLinux_xcb::PumpSystemEventLoopOnce() + void XcbApplication::PumpSystemEventLoopOnce() { if (xcb_connection_t* xcbConnection = m_xcbConnectionManager->GetXcbConnection()) { if (xcb_generic_event_t* event = xcb_poll_for_event(xcbConnection)) { - LinuxXcbEventHandlerBus::Broadcast(&LinuxXcbEventHandlerBus::Events::HandleXcbEvent, event); + XcbEventHandlerBus::Broadcast(&XcbEventHandlerBus::Events::HandleXcbEvent, event); free(event); } } } //////////////////////////////////////////////////////////////////////////////////////////////// - void ApplicationLinux_xcb::PumpSystemEventLoopUntilEmpty() + void XcbApplication::PumpSystemEventLoopUntilEmpty() { if (xcb_connection_t* xcbConnection = m_xcbConnectionManager->GetXcbConnection()) { while (xcb_generic_event_t* event = xcb_poll_for_event(xcbConnection)) { - LinuxXcbEventHandlerBus::Broadcast(&LinuxXcbEventHandlerBus::Events::HandleXcbEvent, event); + XcbEventHandlerBus::Broadcast(&XcbEventHandlerBus::Events::HandleXcbEvent, event); free(event); } } } -#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - } // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbApplication.h b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbApplication.h index fbd7f165d3..f27b5dd680 100644 --- a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbApplication.h +++ b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbApplication.h @@ -5,27 +5,24 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ + #pragma once #include #include +#include -//////////////////////////////////////////////////////////////////////////////////////////////////// namespace AzFramework { - -#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - - //////////////////////////////////////////////////////////////////////////////////////////////// - class ApplicationLinux_xcb + class XcbApplication : public Application::Implementation , public LinuxLifecycleEvents::Bus::Handler { public: //////////////////////////////////////////////////////////////////////////////////////////// - AZ_CLASS_ALLOCATOR(ApplicationLinux_xcb, AZ::SystemAllocator, 0); - ApplicationLinux_xcb(); - ~ApplicationLinux_xcb() override; + AZ_CLASS_ALLOCATOR(XcbApplication, AZ::SystemAllocator, 0); + XcbApplication(); + ~XcbApplication() override; //////////////////////////////////////////////////////////////////////////////////////////// // Application::Implementation @@ -33,9 +30,6 @@ namespace AzFramework void PumpSystemEventLoopUntilEmpty() override; private: - AZStd::unique_ptr m_xcbConnectionManager; + AZStd::unique_ptr m_xcbConnectionManager; }; - -#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - } // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbConnectionManager.h b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbConnectionManager.h new file mode 100644 index 0000000000..daa5bf35af --- /dev/null +++ b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbConnectionManager.h @@ -0,0 +1,42 @@ +/* + * 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 + * + */ + +#pragma once + +#include +#include +#include + +#include + +namespace AzFramework +{ + class XcbConnectionManager + { + public: + AZ_RTTI(XcbConnectionManager, "{1F756E14-8D74-42FD-843C-4863307710DB}"); + + virtual ~XcbConnectionManager() = default; + + virtual xcb_connection_t* GetXcbConnection() const = 0; + }; + + class XcbConnectionManagerBusTraits + : public AZ::EBusTraits + { + public: + ////////////////////////////////////////////////////////////////////////// + // EBusTraits overrides + static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; + static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + ////////////////////////////////////////////////////////////////////////// + }; + + using XcbConnectionManagerBus = AZ::EBus; + using XcbConnectionManagerInterface = AZ::Interface; +} // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbEventHandler.h b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbEventHandler.h new file mode 100644 index 0000000000..c6307755a7 --- /dev/null +++ b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbEventHandler.h @@ -0,0 +1,40 @@ +/* + * 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 + * + */ + +#pragma once + +#include +#include + +#include + +namespace AzFramework +{ + class XcbEventHandler + { + public: + AZ_RTTI(XcbEventHandler, "{3F756E14-8D74-42FD-843C-4863307710DB}"); + + virtual ~XcbEventHandler() = default; + + virtual void HandleXcbEvent(xcb_generic_event_t* event) = 0; + }; + + class XcbEventHandlerBusTraits + : public AZ::EBusTraits + { + public: + ////////////////////////////////////////////////////////////////////////// + // EBusTraits overrides + static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; + static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + ////////////////////////////////////////////////////////////////////////// + }; + + using XcbEventHandlerBus = AZ::EBus; +} // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInputDeviceKeyboard.cpp b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInputDeviceKeyboard.cpp index 8ff4c72d42..c971c3b793 100644 --- a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInputDeviceKeyboard.cpp +++ b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInputDeviceKeyboard.cpp @@ -6,9 +6,10 @@ * */ -#include -#include #include +#include +#include +#include #define explicit ExplicitIsACXXKeyword #include @@ -19,275 +20,252 @@ namespace AzFramework { - class InputDeviceKeyboardXcb - : public InputDeviceKeyboard::Implementation - , public LinuxXcbEventHandlerBus::Handler + XcbInputDeviceKeyboard::XcbInputDeviceKeyboard(InputDeviceKeyboard& inputDevice) + : InputDeviceKeyboard::Implementation(inputDevice) { - public: - AZ_CLASS_ALLOCATOR(InputDeviceKeyboardXcb, AZ::SystemAllocator, 0); + XcbEventHandlerBus::Handler::BusConnect(); - using InputDeviceKeyboard::Implementation::Implementation; - InputDeviceKeyboardXcb(InputDeviceKeyboard& inputDevice) - : InputDeviceKeyboard::Implementation(inputDevice) + auto* interface = AzFramework::XcbConnectionManagerInterface::Get(); + if (!interface) { - LinuxXcbEventHandlerBus::Handler::BusConnect(); - - auto* interface = AzFramework::LinuxXcbConnectionManagerInterface::Get(); - if (!interface) - { - AZ_Warning("ApplicationLinux", false, "XCB interface not available"); - return; - } - - auto* connection = AzFramework::LinuxXcbConnectionManagerInterface::Get()->GetXcbConnection(); - if (!connection) - { - AZ_Warning("ApplicationLinux", false, "XCB connection not available"); - return; - } - - AZStd::unique_ptr> xkbUseExtensionReply{ - xcb_xkb_use_extension_reply(connection, xcb_xkb_use_extension(connection, 1, 0), nullptr) - }; - if (!xkbUseExtensionReply) - { - AZ_Warning("ApplicationLinux", false, "Failed to initialize the xkb extension"); - return; - } - if (!xkbUseExtensionReply->supported) - { - AZ_Warning("ApplicationLinux", false, "The X server does not support the xkb extension"); - return; - } - - m_coreDeviceId = xkb_x11_get_core_keyboard_device_id(connection); - - m_xkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_FLAGS)); - m_xkbKeymap.reset(xkb_x11_keymap_new_from_device(m_xkbContext.get(), connection, m_coreDeviceId, XKB_KEYMAP_COMPILE_NO_FLAGS)); - m_xkbState.reset(xkb_x11_state_new_from_device(m_xkbKeymap.get(), connection, m_coreDeviceId)); - - m_initialized = true; + AZ_Warning("ApplicationLinux", false, "XCB interface not available"); + return; } - bool IsConnected() const override + auto* connection = interface->GetXcbConnection(); + if (!connection) { - return m_initialized; + AZ_Warning("ApplicationLinux", false, "XCB connection not available"); + return; } - bool HasTextEntryStarted() const override + XcbStdFreePtr xkbUseExtensionReply{ + xcb_xkb_use_extension_reply(connection, xcb_xkb_use_extension(connection, 1, 0), nullptr) + }; + if (!xkbUseExtensionReply) { - return false; + AZ_Warning("ApplicationLinux", false, "Failed to initialize the xkb extension"); + return; } - - void TextEntryStart(const InputDeviceKeyboard::VirtualKeyboardOptions& options) override + if (!xkbUseExtensionReply->supported) { + AZ_Warning("ApplicationLinux", false, "The X server does not support the xkb extension"); + return; } - void TextEntryStop() override - { - } + m_coreDeviceId = xkb_x11_get_core_keyboard_device_id(connection); + + m_xkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_FLAGS)); + m_xkbKeymap.reset(xkb_x11_keymap_new_from_device(m_xkbContext.get(), connection, m_coreDeviceId, XKB_KEYMAP_COMPILE_NO_FLAGS)); + m_xkbState.reset(xkb_x11_state_new_from_device(m_xkbKeymap.get(), connection, m_coreDeviceId)); - void TickInputDevice() override + m_initialized = true; + } + + bool XcbInputDeviceKeyboard::IsConnected() const + { + auto* connection = AzFramework::XcbConnectionManagerInterface::Get()->GetXcbConnection(); + return connection && !xcb_connection_has_error(connection); + } + + bool XcbInputDeviceKeyboard::HasTextEntryStarted() const + { + return false; + } + + void XcbInputDeviceKeyboard::TextEntryStart(const InputDeviceKeyboard::VirtualKeyboardOptions& options) + { + } + + void XcbInputDeviceKeyboard::TextEntryStop() + { + } + + void XcbInputDeviceKeyboard::TickInputDevice() + { + ProcessRawEventQueues(); + } + + void XcbInputDeviceKeyboard::HandleXcbEvent(xcb_generic_event_t* event) + { + if (!m_initialized) { - ProcessRawEventQueues(); + return; } - void HandleXcbEvent(xcb_generic_event_t* event) override + switch (event->response_type & ~0x80) { - if (!IsConnected()) - { - return; - } - - switch (event->response_type & ~0x80) - { - case XCB_KEY_PRESS: - { - auto* keyPress = reinterpret_cast(event); + case XCB_KEY_PRESS: + { + auto* keyPress = reinterpret_cast(event); - const InputChannelId* key = InputChannelFromKeyEvent(keyPress->detail); - if (key) - { - QueueRawKeyEvent(*key, true); - } - break; - } - case XCB_KEY_RELEASE: + const InputChannelId* key = InputChannelFromKeyEvent(keyPress->detail); + if (key) { - auto* keyRelease = reinterpret_cast(event); - - const InputChannelId* key = InputChannelFromKeyEvent(keyRelease->detail); - if (key) - { - QueueRawKeyEvent(*key, false); - } - break; - } + QueueRawKeyEvent(*key, true); } + break; } - - private: - [[nodiscard]] const InputChannelId* InputChannelFromKeyEvent(xcb_keycode_t code) const + case XCB_KEY_RELEASE: { - const xcb_keysym_t keysym = xkb_state_key_get_one_sym(m_xkbState.get(), code); + auto* keyRelease = reinterpret_cast(event); - switch(keysym) + const InputChannelId* key = InputChannelFromKeyEvent(keyRelease->detail); + if (key) { - case XKB_KEY_0: return &InputDeviceKeyboard::Key::Alphanumeric0; - case XKB_KEY_1: return &InputDeviceKeyboard::Key::Alphanumeric1; - case XKB_KEY_2: return &InputDeviceKeyboard::Key::Alphanumeric2; - case XKB_KEY_3: return &InputDeviceKeyboard::Key::Alphanumeric3; - case XKB_KEY_4: return &InputDeviceKeyboard::Key::Alphanumeric4; - case XKB_KEY_5: return &InputDeviceKeyboard::Key::Alphanumeric5; - case XKB_KEY_6: return &InputDeviceKeyboard::Key::Alphanumeric6; - case XKB_KEY_7: return &InputDeviceKeyboard::Key::Alphanumeric7; - case XKB_KEY_8: return &InputDeviceKeyboard::Key::Alphanumeric8; - case XKB_KEY_9: return &InputDeviceKeyboard::Key::Alphanumeric9; - case XKB_KEY_A: - case XKB_KEY_a: return &InputDeviceKeyboard::Key::AlphanumericA; - case XKB_KEY_B: - case XKB_KEY_b: return &InputDeviceKeyboard::Key::AlphanumericB; - case XKB_KEY_C: - case XKB_KEY_c: return &InputDeviceKeyboard::Key::AlphanumericC; - case XKB_KEY_D: - case XKB_KEY_d: return &InputDeviceKeyboard::Key::AlphanumericD; - case XKB_KEY_E: - case XKB_KEY_e: return &InputDeviceKeyboard::Key::AlphanumericE; - case XKB_KEY_F: - case XKB_KEY_f: return &InputDeviceKeyboard::Key::AlphanumericF; - case XKB_KEY_G: - case XKB_KEY_g: return &InputDeviceKeyboard::Key::AlphanumericG; - case XKB_KEY_H: - case XKB_KEY_h: return &InputDeviceKeyboard::Key::AlphanumericH; - case XKB_KEY_I: - case XKB_KEY_i: return &InputDeviceKeyboard::Key::AlphanumericI; - case XKB_KEY_J: - case XKB_KEY_j: return &InputDeviceKeyboard::Key::AlphanumericJ; - case XKB_KEY_K: - case XKB_KEY_k: return &InputDeviceKeyboard::Key::AlphanumericK; - case XKB_KEY_L: - case XKB_KEY_l: return &InputDeviceKeyboard::Key::AlphanumericL; - case XKB_KEY_M: - case XKB_KEY_m: return &InputDeviceKeyboard::Key::AlphanumericM; - case XKB_KEY_N: - case XKB_KEY_n: return &InputDeviceKeyboard::Key::AlphanumericN; - case XKB_KEY_O: - case XKB_KEY_o: return &InputDeviceKeyboard::Key::AlphanumericO; - case XKB_KEY_P: - case XKB_KEY_p: return &InputDeviceKeyboard::Key::AlphanumericP; - case XKB_KEY_Q: - case XKB_KEY_q: return &InputDeviceKeyboard::Key::AlphanumericQ; - case XKB_KEY_R: - case XKB_KEY_r: return &InputDeviceKeyboard::Key::AlphanumericR; - case XKB_KEY_S: - case XKB_KEY_s: return &InputDeviceKeyboard::Key::AlphanumericS; - case XKB_KEY_T: - case XKB_KEY_t: return &InputDeviceKeyboard::Key::AlphanumericT; - case XKB_KEY_U: - case XKB_KEY_u: return &InputDeviceKeyboard::Key::AlphanumericU; - case XKB_KEY_V: - case XKB_KEY_v: return &InputDeviceKeyboard::Key::AlphanumericV; - case XKB_KEY_W: - case XKB_KEY_w: return &InputDeviceKeyboard::Key::AlphanumericW; - case XKB_KEY_X: - case XKB_KEY_x: return &InputDeviceKeyboard::Key::AlphanumericX; - case XKB_KEY_Y: - case XKB_KEY_y: return &InputDeviceKeyboard::Key::AlphanumericY; - case XKB_KEY_Z: - case XKB_KEY_z: return &InputDeviceKeyboard::Key::AlphanumericZ; - case XKB_KEY_BackSpace: return &InputDeviceKeyboard::Key::EditBackspace; - case XKB_KEY_Caps_Lock: return &InputDeviceKeyboard::Key::EditCapsLock; - case XKB_KEY_Return: return &InputDeviceKeyboard::Key::EditEnter; - case XKB_KEY_space: return &InputDeviceKeyboard::Key::EditSpace; - case XKB_KEY_Tab: return &InputDeviceKeyboard::Key::EditTab; - case XKB_KEY_Escape: return &InputDeviceKeyboard::Key::Escape; - case XKB_KEY_F1: return &InputDeviceKeyboard::Key::Function01; - case XKB_KEY_F2: return &InputDeviceKeyboard::Key::Function02; - case XKB_KEY_F3: return &InputDeviceKeyboard::Key::Function03; - case XKB_KEY_F4: return &InputDeviceKeyboard::Key::Function04; - case XKB_KEY_F5: return &InputDeviceKeyboard::Key::Function05; - case XKB_KEY_F6: return &InputDeviceKeyboard::Key::Function06; - case XKB_KEY_F7: return &InputDeviceKeyboard::Key::Function07; - case XKB_KEY_F8: return &InputDeviceKeyboard::Key::Function08; - case XKB_KEY_F9: return &InputDeviceKeyboard::Key::Function09; - case XKB_KEY_F10: return &InputDeviceKeyboard::Key::Function10; - case XKB_KEY_F11: return &InputDeviceKeyboard::Key::Function11; - case XKB_KEY_F12: return &InputDeviceKeyboard::Key::Function12; - case XKB_KEY_F13: return &InputDeviceKeyboard::Key::Function13; - case XKB_KEY_F14: return &InputDeviceKeyboard::Key::Function14; - case XKB_KEY_F15: return &InputDeviceKeyboard::Key::Function15; - case XKB_KEY_F16: return &InputDeviceKeyboard::Key::Function16; - case XKB_KEY_F17: return &InputDeviceKeyboard::Key::Function17; - case XKB_KEY_F18: return &InputDeviceKeyboard::Key::Function18; - case XKB_KEY_F19: return &InputDeviceKeyboard::Key::Function19; - case XKB_KEY_F20: return &InputDeviceKeyboard::Key::Function20; - case XKB_KEY_Alt_L: return &InputDeviceKeyboard::Key::ModifierAltL; - case XKB_KEY_Alt_R: return &InputDeviceKeyboard::Key::ModifierAltR; - case XKB_KEY_Control_L: return &InputDeviceKeyboard::Key::ModifierCtrlL; - case XKB_KEY_Control_R: return &InputDeviceKeyboard::Key::ModifierCtrlR; - case XKB_KEY_Shift_L: return &InputDeviceKeyboard::Key::ModifierShiftL; - case XKB_KEY_Shift_R: return &InputDeviceKeyboard::Key::ModifierShiftR; - case XKB_KEY_Super_L: return &InputDeviceKeyboard::Key::ModifierSuperL; - case XKB_KEY_Super_R: return &InputDeviceKeyboard::Key::ModifierSuperR; - case XKB_KEY_Down: return &InputDeviceKeyboard::Key::NavigationArrowDown; - case XKB_KEY_Left: return &InputDeviceKeyboard::Key::NavigationArrowLeft; - case XKB_KEY_Right: return &InputDeviceKeyboard::Key::NavigationArrowRight; - case XKB_KEY_Up: return &InputDeviceKeyboard::Key::NavigationArrowUp; - case XKB_KEY_Delete: return &InputDeviceKeyboard::Key::NavigationDelete; - case XKB_KEY_End: return &InputDeviceKeyboard::Key::NavigationEnd; - case XKB_KEY_Home: return &InputDeviceKeyboard::Key::NavigationHome; - case XKB_KEY_Insert: return &InputDeviceKeyboard::Key::NavigationInsert; - case XKB_KEY_Page_Down: return &InputDeviceKeyboard::Key::NavigationPageDown; - case XKB_KEY_Page_Up: return &InputDeviceKeyboard::Key::NavigationPageUp; - case XKB_KEY_Num_Lock: return &InputDeviceKeyboard::Key::NumLock; - case XKB_KEY_KP_0: return &InputDeviceKeyboard::Key::NumPad0; - case XKB_KEY_KP_1: return &InputDeviceKeyboard::Key::NumPad1; - case XKB_KEY_KP_2: return &InputDeviceKeyboard::Key::NumPad2; - case XKB_KEY_KP_3: return &InputDeviceKeyboard::Key::NumPad3; - case XKB_KEY_KP_4: return &InputDeviceKeyboard::Key::NumPad4; - case XKB_KEY_KP_5: return &InputDeviceKeyboard::Key::NumPad5; - case XKB_KEY_KP_6: return &InputDeviceKeyboard::Key::NumPad6; - case XKB_KEY_KP_7: return &InputDeviceKeyboard::Key::NumPad7; - case XKB_KEY_KP_8: return &InputDeviceKeyboard::Key::NumPad8; - case XKB_KEY_KP_9: return &InputDeviceKeyboard::Key::NumPad9; - case XKB_KEY_KP_Add: return &InputDeviceKeyboard::Key::NumPadAdd; - case XKB_KEY_KP_Decimal: return &InputDeviceKeyboard::Key::NumPadDecimal; - case XKB_KEY_KP_Divide: return &InputDeviceKeyboard::Key::NumPadDivide; - case XKB_KEY_KP_Enter: return &InputDeviceKeyboard::Key::NumPadEnter; - case XKB_KEY_KP_Multiply: return &InputDeviceKeyboard::Key::NumPadMultiply; - case XKB_KEY_KP_Subtract: return &InputDeviceKeyboard::Key::NumPadSubtract; - case XKB_KEY_apostrophe: return &InputDeviceKeyboard::Key::PunctuationApostrophe; - case XKB_KEY_backslash: return &InputDeviceKeyboard::Key::PunctuationBackslash; - case XKB_KEY_bracketleft: return &InputDeviceKeyboard::Key::PunctuationBracketL; - case XKB_KEY_bracketright: return &InputDeviceKeyboard::Key::PunctuationBracketR; - case XKB_KEY_comma: return &InputDeviceKeyboard::Key::PunctuationComma; - case XKB_KEY_equal: return &InputDeviceKeyboard::Key::PunctuationEquals; - case XKB_KEY_hyphen: return &InputDeviceKeyboard::Key::PunctuationHyphen; - case XKB_KEY_period: return &InputDeviceKeyboard::Key::PunctuationPeriod; - case XKB_KEY_semicolon: return &InputDeviceKeyboard::Key::PunctuationSemicolon; - case XKB_KEY_slash: return &InputDeviceKeyboard::Key::PunctuationSlash; - case XKB_KEY_grave: - case XKB_KEY_asciitilde: return &InputDeviceKeyboard::Key::PunctuationTilde; - case XKB_KEY_ISO_Group_Shift: return &InputDeviceKeyboard::Key::SupplementaryISO; - case XKB_KEY_Pause: return &InputDeviceKeyboard::Key::WindowsSystemPause; - case XKB_KEY_Print: return &InputDeviceKeyboard::Key::WindowsSystemPrint; - case XKB_KEY_Scroll_Lock: return &InputDeviceKeyboard::Key::WindowsSystemScrollLock; - default: return nullptr; + QueueRawKeyEvent(*key, false); } + break; } + } + } - template - using DeleterForFreeFn = AZStd::integral_constant; - - AZStd::unique_ptr> m_xkbContext; - AZStd::unique_ptr> m_xkbKeymap; - AZStd::unique_ptr> m_xkbState; - int m_coreDeviceId{-1}; - bool m_initialized{false}; - }; - - InputDeviceKeyboard::Implementation* InputDeviceKeyboard::Implementation::Create(InputDeviceKeyboard& inputDevice) + [[nodiscard]] const InputChannelId* XcbInputDeviceKeyboard::InputChannelFromKeyEvent(xcb_keycode_t code) const { - return aznew InputDeviceKeyboardXcb(inputDevice); + const xcb_keysym_t keysym = xkb_state_key_get_one_sym(m_xkbState.get(), code); + + switch(keysym) + { + case XKB_KEY_0: return &InputDeviceKeyboard::Key::Alphanumeric0; + case XKB_KEY_1: return &InputDeviceKeyboard::Key::Alphanumeric1; + case XKB_KEY_2: return &InputDeviceKeyboard::Key::Alphanumeric2; + case XKB_KEY_3: return &InputDeviceKeyboard::Key::Alphanumeric3; + case XKB_KEY_4: return &InputDeviceKeyboard::Key::Alphanumeric4; + case XKB_KEY_5: return &InputDeviceKeyboard::Key::Alphanumeric5; + case XKB_KEY_6: return &InputDeviceKeyboard::Key::Alphanumeric6; + case XKB_KEY_7: return &InputDeviceKeyboard::Key::Alphanumeric7; + case XKB_KEY_8: return &InputDeviceKeyboard::Key::Alphanumeric8; + case XKB_KEY_9: return &InputDeviceKeyboard::Key::Alphanumeric9; + case XKB_KEY_A: + case XKB_KEY_a: return &InputDeviceKeyboard::Key::AlphanumericA; + case XKB_KEY_B: + case XKB_KEY_b: return &InputDeviceKeyboard::Key::AlphanumericB; + case XKB_KEY_C: + case XKB_KEY_c: return &InputDeviceKeyboard::Key::AlphanumericC; + case XKB_KEY_D: + case XKB_KEY_d: return &InputDeviceKeyboard::Key::AlphanumericD; + case XKB_KEY_E: + case XKB_KEY_e: return &InputDeviceKeyboard::Key::AlphanumericE; + case XKB_KEY_F: + case XKB_KEY_f: return &InputDeviceKeyboard::Key::AlphanumericF; + case XKB_KEY_G: + case XKB_KEY_g: return &InputDeviceKeyboard::Key::AlphanumericG; + case XKB_KEY_H: + case XKB_KEY_h: return &InputDeviceKeyboard::Key::AlphanumericH; + case XKB_KEY_I: + case XKB_KEY_i: return &InputDeviceKeyboard::Key::AlphanumericI; + case XKB_KEY_J: + case XKB_KEY_j: return &InputDeviceKeyboard::Key::AlphanumericJ; + case XKB_KEY_K: + case XKB_KEY_k: return &InputDeviceKeyboard::Key::AlphanumericK; + case XKB_KEY_L: + case XKB_KEY_l: return &InputDeviceKeyboard::Key::AlphanumericL; + case XKB_KEY_M: + case XKB_KEY_m: return &InputDeviceKeyboard::Key::AlphanumericM; + case XKB_KEY_N: + case XKB_KEY_n: return &InputDeviceKeyboard::Key::AlphanumericN; + case XKB_KEY_O: + case XKB_KEY_o: return &InputDeviceKeyboard::Key::AlphanumericO; + case XKB_KEY_P: + case XKB_KEY_p: return &InputDeviceKeyboard::Key::AlphanumericP; + case XKB_KEY_Q: + case XKB_KEY_q: return &InputDeviceKeyboard::Key::AlphanumericQ; + case XKB_KEY_R: + case XKB_KEY_r: return &InputDeviceKeyboard::Key::AlphanumericR; + case XKB_KEY_S: + case XKB_KEY_s: return &InputDeviceKeyboard::Key::AlphanumericS; + case XKB_KEY_T: + case XKB_KEY_t: return &InputDeviceKeyboard::Key::AlphanumericT; + case XKB_KEY_U: + case XKB_KEY_u: return &InputDeviceKeyboard::Key::AlphanumericU; + case XKB_KEY_V: + case XKB_KEY_v: return &InputDeviceKeyboard::Key::AlphanumericV; + case XKB_KEY_W: + case XKB_KEY_w: return &InputDeviceKeyboard::Key::AlphanumericW; + case XKB_KEY_X: + case XKB_KEY_x: return &InputDeviceKeyboard::Key::AlphanumericX; + case XKB_KEY_Y: + case XKB_KEY_y: return &InputDeviceKeyboard::Key::AlphanumericY; + case XKB_KEY_Z: + case XKB_KEY_z: return &InputDeviceKeyboard::Key::AlphanumericZ; + case XKB_KEY_BackSpace: return &InputDeviceKeyboard::Key::EditBackspace; + case XKB_KEY_Caps_Lock: return &InputDeviceKeyboard::Key::EditCapsLock; + case XKB_KEY_Return: return &InputDeviceKeyboard::Key::EditEnter; + case XKB_KEY_space: return &InputDeviceKeyboard::Key::EditSpace; + case XKB_KEY_Tab: return &InputDeviceKeyboard::Key::EditTab; + case XKB_KEY_Escape: return &InputDeviceKeyboard::Key::Escape; + case XKB_KEY_F1: return &InputDeviceKeyboard::Key::Function01; + case XKB_KEY_F2: return &InputDeviceKeyboard::Key::Function02; + case XKB_KEY_F3: return &InputDeviceKeyboard::Key::Function03; + case XKB_KEY_F4: return &InputDeviceKeyboard::Key::Function04; + case XKB_KEY_F5: return &InputDeviceKeyboard::Key::Function05; + case XKB_KEY_F6: return &InputDeviceKeyboard::Key::Function06; + case XKB_KEY_F7: return &InputDeviceKeyboard::Key::Function07; + case XKB_KEY_F8: return &InputDeviceKeyboard::Key::Function08; + case XKB_KEY_F9: return &InputDeviceKeyboard::Key::Function09; + case XKB_KEY_F10: return &InputDeviceKeyboard::Key::Function10; + case XKB_KEY_F11: return &InputDeviceKeyboard::Key::Function11; + case XKB_KEY_F12: return &InputDeviceKeyboard::Key::Function12; + case XKB_KEY_F13: return &InputDeviceKeyboard::Key::Function13; + case XKB_KEY_F14: return &InputDeviceKeyboard::Key::Function14; + case XKB_KEY_F15: return &InputDeviceKeyboard::Key::Function15; + case XKB_KEY_F16: return &InputDeviceKeyboard::Key::Function16; + case XKB_KEY_F17: return &InputDeviceKeyboard::Key::Function17; + case XKB_KEY_F18: return &InputDeviceKeyboard::Key::Function18; + case XKB_KEY_F19: return &InputDeviceKeyboard::Key::Function19; + case XKB_KEY_F20: return &InputDeviceKeyboard::Key::Function20; + case XKB_KEY_Alt_L: return &InputDeviceKeyboard::Key::ModifierAltL; + case XKB_KEY_Alt_R: return &InputDeviceKeyboard::Key::ModifierAltR; + case XKB_KEY_Control_L: return &InputDeviceKeyboard::Key::ModifierCtrlL; + case XKB_KEY_Control_R: return &InputDeviceKeyboard::Key::ModifierCtrlR; + case XKB_KEY_Shift_L: return &InputDeviceKeyboard::Key::ModifierShiftL; + case XKB_KEY_Shift_R: return &InputDeviceKeyboard::Key::ModifierShiftR; + case XKB_KEY_Super_L: return &InputDeviceKeyboard::Key::ModifierSuperL; + case XKB_KEY_Super_R: return &InputDeviceKeyboard::Key::ModifierSuperR; + case XKB_KEY_Down: return &InputDeviceKeyboard::Key::NavigationArrowDown; + case XKB_KEY_Left: return &InputDeviceKeyboard::Key::NavigationArrowLeft; + case XKB_KEY_Right: return &InputDeviceKeyboard::Key::NavigationArrowRight; + case XKB_KEY_Up: return &InputDeviceKeyboard::Key::NavigationArrowUp; + case XKB_KEY_Delete: return &InputDeviceKeyboard::Key::NavigationDelete; + case XKB_KEY_End: return &InputDeviceKeyboard::Key::NavigationEnd; + case XKB_KEY_Home: return &InputDeviceKeyboard::Key::NavigationHome; + case XKB_KEY_Insert: return &InputDeviceKeyboard::Key::NavigationInsert; + case XKB_KEY_Page_Down: return &InputDeviceKeyboard::Key::NavigationPageDown; + case XKB_KEY_Page_Up: return &InputDeviceKeyboard::Key::NavigationPageUp; + case XKB_KEY_Num_Lock: return &InputDeviceKeyboard::Key::NumLock; + case XKB_KEY_KP_0: return &InputDeviceKeyboard::Key::NumPad0; + case XKB_KEY_KP_1: return &InputDeviceKeyboard::Key::NumPad1; + case XKB_KEY_KP_2: return &InputDeviceKeyboard::Key::NumPad2; + case XKB_KEY_KP_3: return &InputDeviceKeyboard::Key::NumPad3; + case XKB_KEY_KP_4: return &InputDeviceKeyboard::Key::NumPad4; + case XKB_KEY_KP_5: return &InputDeviceKeyboard::Key::NumPad5; + case XKB_KEY_KP_6: return &InputDeviceKeyboard::Key::NumPad6; + case XKB_KEY_KP_7: return &InputDeviceKeyboard::Key::NumPad7; + case XKB_KEY_KP_8: return &InputDeviceKeyboard::Key::NumPad8; + case XKB_KEY_KP_9: return &InputDeviceKeyboard::Key::NumPad9; + case XKB_KEY_KP_Add: return &InputDeviceKeyboard::Key::NumPadAdd; + case XKB_KEY_KP_Decimal: return &InputDeviceKeyboard::Key::NumPadDecimal; + case XKB_KEY_KP_Divide: return &InputDeviceKeyboard::Key::NumPadDivide; + case XKB_KEY_KP_Enter: return &InputDeviceKeyboard::Key::NumPadEnter; + case XKB_KEY_KP_Multiply: return &InputDeviceKeyboard::Key::NumPadMultiply; + case XKB_KEY_KP_Subtract: return &InputDeviceKeyboard::Key::NumPadSubtract; + case XKB_KEY_apostrophe: return &InputDeviceKeyboard::Key::PunctuationApostrophe; + case XKB_KEY_backslash: return &InputDeviceKeyboard::Key::PunctuationBackslash; + case XKB_KEY_bracketleft: return &InputDeviceKeyboard::Key::PunctuationBracketL; + case XKB_KEY_bracketright: return &InputDeviceKeyboard::Key::PunctuationBracketR; + case XKB_KEY_comma: return &InputDeviceKeyboard::Key::PunctuationComma; + case XKB_KEY_equal: return &InputDeviceKeyboard::Key::PunctuationEquals; + case XKB_KEY_hyphen: return &InputDeviceKeyboard::Key::PunctuationHyphen; + case XKB_KEY_period: return &InputDeviceKeyboard::Key::PunctuationPeriod; + case XKB_KEY_semicolon: return &InputDeviceKeyboard::Key::PunctuationSemicolon; + case XKB_KEY_slash: return &InputDeviceKeyboard::Key::PunctuationSlash; + case XKB_KEY_grave: + case XKB_KEY_asciitilde: return &InputDeviceKeyboard::Key::PunctuationTilde; + case XKB_KEY_ISO_Group_Shift: return &InputDeviceKeyboard::Key::SupplementaryISO; + case XKB_KEY_Pause: return &InputDeviceKeyboard::Key::WindowsSystemPause; + case XKB_KEY_Print: return &InputDeviceKeyboard::Key::WindowsSystemPrint; + case XKB_KEY_Scroll_Lock: return &InputDeviceKeyboard::Key::WindowsSystemScrollLock; + default: return nullptr; + } } } // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInputDeviceKeyboard.h b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInputDeviceKeyboard.h new file mode 100644 index 0000000000..de65941a67 --- /dev/null +++ b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInputDeviceKeyboard.h @@ -0,0 +1,46 @@ +/* + * 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 +#include +#include + +#include +#include + +namespace AzFramework +{ + class XcbInputDeviceKeyboard + : public InputDeviceKeyboard::Implementation + , public XcbEventHandlerBus::Handler + { + public: + AZ_CLASS_ALLOCATOR(XcbInputDeviceKeyboard, AZ::SystemAllocator, 0); + + using InputDeviceKeyboard::Implementation::Implementation; + XcbInputDeviceKeyboard(InputDeviceKeyboard& inputDevice); + + bool IsConnected() const override; + + bool HasTextEntryStarted() const override; + void TextEntryStart(const InputDeviceKeyboard::VirtualKeyboardOptions& options) override; + void TextEntryStop() override; + void TickInputDevice() override; + + void HandleXcbEvent(xcb_generic_event_t* event) override; + + private: + [[nodiscard]] const InputChannelId* InputChannelFromKeyEvent(xcb_keycode_t code) const; + + XcbUniquePtr m_xkbContext; + XcbUniquePtr m_xkbKeymap; + XcbUniquePtr m_xkbState; + int m_coreDeviceId{-1}; + bool m_initialized{false}; + }; +} // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInterface.h b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInterface.h new file mode 100644 index 0000000000..838048b174 --- /dev/null +++ b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbInterface.h @@ -0,0 +1,38 @@ +/* + * 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 + * + */ + +#pragma once + +#include + +#include + +namespace AzFramework +{ + // @brief Wrap a function pointer in a type + // This serves as a convenient way to wrap a function pointer in a given + // type. That type can then be used in a `unique_ptr` or `shared_ptr`. + // Using a type instead of a function pointer by value prevents the need to + // copy the pointer when copying the smart poiner. + template + struct XcbDeleterFreeFunctionWrapper + { + using value_type = decltype(Callable); + static constexpr value_type s_value = Callable; + constexpr operator value_type() const noexcept + { + return s_value; + } + }; + + template + using XcbUniquePtr = AZStd::unique_ptr>; + + template + using XcbStdFreePtr = XcbUniquePtr; +} // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbNativeWindow.cpp b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbNativeWindow.cpp index cfc0222214..6ab97fd616 100644 --- a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbNativeWindow.cpp +++ b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbNativeWindow.cpp @@ -6,41 +6,37 @@ * */ -#include #include #include -#include +#include +#include -#include "NativeWindow_Linux_xcb.h" +#include namespace AzFramework { -#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - - [[maybe_unused]] const char LinuxXcbErrorWindow[] = "NativeWindow_Linux_xcb"; + [[maybe_unused]] const char XcbErrorWindow[] = "XcbNativeWindow"; static constexpr uint8_t s_XcbFormatDataSize = 32; // Format indicator for xcb for client messages static constexpr uint16_t s_DefaultXcbWindowBorderWidth = 4; // The default border with in pixels if a border was specified static constexpr uint8_t s_XcbResponseTypeMask = 0x7f; // Mask to extract the specific event type from an xcb event //////////////////////////////////////////////////////////////////////////////////////////////// - NativeWindowImpl_Linux_xcb::NativeWindowImpl_Linux_xcb() + XcbNativeWindow::XcbNativeWindow() : NativeWindow::Implementation() { - if (auto xcbConnectionManager = AzFramework::LinuxXcbConnectionManagerInterface::Get(); + if (auto xcbConnectionManager = AzFramework::XcbConnectionManagerInterface::Get(); xcbConnectionManager != nullptr) { m_xcbConnection = xcbConnectionManager->GetXcbConnection(); } - AZ_Error(LinuxXcbErrorWindow, m_xcbConnection != nullptr, "Unable to get XCB Connection"); + AZ_Error(XcbErrorWindow, m_xcbConnection != nullptr, "Unable to get XCB Connection"); } //////////////////////////////////////////////////////////////////////////////////////////////// - NativeWindowImpl_Linux_xcb::~NativeWindowImpl_Linux_xcb() - { - } + XcbNativeWindow::~XcbNativeWindow() = default; //////////////////////////////////////////////////////////////////////////////////////////////// - void NativeWindowImpl_Linux_xcb::InitWindow(const AZStd::string& title, + void XcbNativeWindow::InitWindow(const AZStd::string& title, const WindowGeometry& geometry, const WindowStyleMasks& styleMasks) { @@ -98,13 +94,13 @@ namespace AzFramework xcb_intern_atom_cookie_t cookieProtocol = xcb_intern_atom(m_xcbConnection, 1, strlen(wmProtocolString), wmProtocolString); xcb_intern_atom_reply_t* replyProtocol = xcb_intern_atom_reply(m_xcbConnection, cookieProtocol, nullptr); - AZ_Error(LinuxXcbErrorWindow, replyProtocol != nullptr, "Unable to query xcb '%s' atom", wmProtocolString); + AZ_Error(XcbErrorWindow, replyProtocol != nullptr, "Unable to query xcb '%s' atom", wmProtocolString); m_xcbAtomProtocols = replyProtocol->atom; const static char* wmDeleteWindowString = "WM_DELETE_WINDOW"; xcb_intern_atom_cookie_t cookieDeleteWindow = xcb_intern_atom(m_xcbConnection, 0, strlen(wmDeleteWindowString), wmDeleteWindowString); xcb_intern_atom_reply_t* replyDeleteWindow = xcb_intern_atom_reply(m_xcbConnection, cookieDeleteWindow, nullptr); - AZ_Error(LinuxXcbErrorWindow, replyDeleteWindow != nullptr, "Unable to query xcb '%s' atom", wmDeleteWindowString); + AZ_Error(XcbErrorWindow, replyDeleteWindow != nullptr, "Unable to query xcb '%s' atom", wmDeleteWindowString); m_xcbAtomDeleteWindow = replyDeleteWindow->atom; xcbCheckResult = xcb_change_property_checked(m_xcbConnection, @@ -123,9 +119,9 @@ namespace AzFramework } //////////////////////////////////////////////////////////////////////////////////////////////// - void NativeWindowImpl_Linux_xcb::Activate() + void XcbNativeWindow::Activate() { - LinuxXcbEventHandlerBus::Handler::BusConnect(); + XcbEventHandlerBus::Handler::BusConnect(); if (!m_activated) // nothing to do if window was already activated { @@ -137,7 +133,7 @@ namespace AzFramework } //////////////////////////////////////////////////////////////////////////////////////////////// - void NativeWindowImpl_Linux_xcb::Deactivate() + void XcbNativeWindow::Deactivate() { if (m_activated) // nothing to do if window was already deactivated { @@ -148,17 +144,17 @@ namespace AzFramework xcb_unmap_window(m_xcbConnection, m_xcbWindow); xcb_flush(m_xcbConnection); } - LinuxXcbEventHandlerBus::Handler::BusDisconnect(); + XcbEventHandlerBus::Handler::BusDisconnect(); } //////////////////////////////////////////////////////////////////////////////////////////////// - NativeWindowHandle NativeWindowImpl_Linux_xcb::GetWindowHandle() const + NativeWindowHandle XcbNativeWindow::GetWindowHandle() const { return reinterpret_cast(m_xcbWindow); } //////////////////////////////////////////////////////////////////////////////////////////////// - void NativeWindowImpl_Linux_xcb::SetWindowTitle(const AZStd::string& title) + void XcbNativeWindow::SetWindowTitle(const AZStd::string& title) { xcb_void_cookie_t xcbCheckResult; xcbCheckResult = xcb_change_property(m_xcbConnection, @@ -173,7 +169,7 @@ namespace AzFramework } //////////////////////////////////////////////////////////////////////////////////////////////// - void NativeWindowImpl_Linux_xcb::ResizeClientArea(WindowSize clientAreaSize) + void XcbNativeWindow::ResizeClientArea(WindowSize clientAreaSize) { const uint32_t values[] = { clientAreaSize.m_width, clientAreaSize.m_height }; @@ -184,7 +180,7 @@ namespace AzFramework } //////////////////////////////////////////////////////////////////////////////////////////////// - uint32_t NativeWindowImpl_Linux_xcb::GetDisplayRefreshRate() const + uint32_t XcbNativeWindow::GetDisplayRefreshRate() const { // [GFX TODO][GHI - 2678] // Using 60 for now until proper support is added @@ -192,7 +188,7 @@ namespace AzFramework } //////////////////////////////////////////////////////////////////////////////////////////////// - bool NativeWindowImpl_Linux_xcb::ValidateXcbResult(xcb_void_cookie_t cookie) + bool XcbNativeWindow::ValidateXcbResult(xcb_void_cookie_t cookie) { bool result = true; if (xcb_generic_error_t* error = xcb_request_check(m_xcbConnection, cookie)) @@ -204,7 +200,7 @@ namespace AzFramework } //////////////////////////////////////////////////////////////////////////////////////////////// - void NativeWindowImpl_Linux_xcb::HandleXcbEvent(xcb_generic_event_t* event) + void XcbNativeWindow::HandleXcbEvent(xcb_generic_event_t* event) { switch (event->response_type & s_XcbResponseTypeMask) { @@ -233,7 +229,7 @@ namespace AzFramework } //////////////////////////////////////////////////////////////////////////////////////////////// - void NativeWindowImpl_Linux_xcb::WindowSizeChanged(const uint32_t width, const uint32_t height) + void XcbNativeWindow::WindowSizeChanged(const uint32_t width, const uint32_t height) { if (m_width != width || m_height != height) { @@ -246,7 +242,4 @@ namespace AzFramework } } } - -#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - } // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbNativeWindow.h b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbNativeWindow.h index 40181395e4..36737e24e8 100644 --- a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbNativeWindow.h +++ b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbNativeWindow.h @@ -5,24 +5,25 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ + #pragma once -#include #include #include +#include + #include namespace AzFramework { -#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - class NativeWindowImpl_Linux_xcb final + class XcbNativeWindow final : public NativeWindow::Implementation - , public LinuxXcbEventHandlerBus::Handler + , public XcbEventHandlerBus::Handler { public: - AZ_CLASS_ALLOCATOR(NativeWindowImpl_Linux_xcb, AZ::SystemAllocator, 0); - NativeWindowImpl_Linux_xcb(); - ~NativeWindowImpl_Linux_xcb() override; + AZ_CLASS_ALLOCATOR(XcbNativeWindow, AZ::SystemAllocator, 0); + XcbNativeWindow(); + ~XcbNativeWindow() override; //////////////////////////////////////////////////////////////////////////////////////////// // NativeWindow::Implementation @@ -37,7 +38,7 @@ namespace AzFramework uint32_t GetDisplayRefreshRate() const override; //////////////////////////////////////////////////////////////////////////////////////////// - // LinuxXcbEventHandlerBus::Handler + // XcbEventHandlerBus::Handler void HandleXcbEvent(xcb_generic_event_t* event) override; private: @@ -49,6 +50,4 @@ namespace AzFramework xcb_atom_t m_xcbAtomProtocols; xcb_atom_t m_xcbAtomDeleteWindow; }; -#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - } // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Common/Xcb/azframework_xcb_files.cmake b/Code/Framework/AzFramework/Platform/Common/Xcb/azframework_xcb_files.cmake new file mode 100644 index 0000000000..68de710fa1 --- /dev/null +++ b/Code/Framework/AzFramework/Platform/Common/Xcb/azframework_xcb_files.cmake @@ -0,0 +1,18 @@ +# +# 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 +# +# + +set(FILES + AzFramework/XcbApplication.cpp + AzFramework/XcbApplication.h + AzFramework/XcbConnectionManager.h + AzFramework/XcbInputDeviceKeyboard.cpp + AzFramework/XcbInputDeviceKeyboard.h + AzFramework/XcbInterface.h + AzFramework/XcbNativeWindow.cpp + AzFramework/XcbNativeWindow.h +) diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h b/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h index 833f4019f8..adf3ee0bdd 100644 --- a/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/API/ApplicationAPI_Linux.h @@ -12,10 +12,6 @@ #include #include -#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB -#include -#endif // LY_COMPILE_DEFINITIONS - namespace AzFramework { class LinuxLifecycleEvents @@ -30,54 +26,4 @@ namespace AzFramework using Bus = AZ::EBus; }; - -#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - class LinuxXcbConnectionManager - { - public: - AZ_RTTI(LinuxXcbConnectionManager, "{1F756E14-8D74-42FD-843C-4863307710DB}"); - - virtual ~LinuxXcbConnectionManager() = default; - - virtual xcb_connection_t* GetXcbConnection() const = 0; - }; - - class LinuxXcbConnectionManagerBusTraits - : public AZ::EBusTraits - { - public: - ////////////////////////////////////////////////////////////////////////// - // EBusTraits overrides - static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; - static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - ////////////////////////////////////////////////////////////////////////// - }; - - using LinuxXcbConnectionManagerBus = AZ::EBus; - using LinuxXcbConnectionManagerInterface = AZ::Interface; - - class LinuxXcbEventHandler - { - public: - AZ_RTTI(LinuxXcbEventHandler, "{3F756E14-8D74-42FD-843C-4863307710DB}"); - - virtual ~LinuxXcbEventHandler() = default; - - virtual void HandleXcbEvent(xcb_generic_event_t* event) = 0; - }; - - class LinuxXcbEventHandlerBusTraits - : public AZ::EBusTraits - { - public: - ////////////////////////////////////////////////////////////////////////// - // EBusTraits overrides - static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; - static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - ////////////////////////////////////////////////////////////////////////// - }; - - using LinuxXcbEventHandlerBus = AZ::EBus; - -#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB } // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux.cpp b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux.cpp index 59602fe788..158240210e 100644 --- a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux.cpp +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Application/Application_Linux.cpp @@ -8,7 +8,9 @@ #include -#include "Application_Linux_xcb.h" +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB +#include +#endif //////////////////////////////////////////////////////////////////////////////////////////////////// namespace AzFramework @@ -17,7 +19,7 @@ namespace AzFramework Application::Implementation* Application::Implementation::Create() { #if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - return aznew ApplicationLinux_xcb(); + return aznew XcbApplication(); #elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND #error "Linux Window Manager Wayland not supported." return nullptr; diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Linux.cpp b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Linux.cpp new file mode 100644 index 0000000000..d1f90c3052 --- /dev/null +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Linux.cpp @@ -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 + * + */ + +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB +#include +#endif + +namespace AzFramework +{ + InputDeviceKeyboard::Implementation* InputDeviceKeyboard::Implementation::Create(InputDeviceKeyboard& inputDevice) + { +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + return aznew XcbInputDeviceKeyboard(inputDevice); +#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND + #error "Linux Window Manager Wayland not supported." + return nullptr; +#else + #error "Linux Window Manager not recognized." + return nullptr; +#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB + } +} // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Windowing/NativeWindow_Linux.cpp b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Windowing/NativeWindow_Linux.cpp index 2950f8dcfc..ba3e761974 100644 --- a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Windowing/NativeWindow_Linux.cpp +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Windowing/NativeWindow_Linux.cpp @@ -6,14 +6,16 @@ * */ -#include "NativeWindow_Linux_xcb.h" +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB +#include +#endif namespace AzFramework { NativeWindow::Implementation* NativeWindow::Implementation::Create() { #if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - return aznew NativeWindowImpl_Linux_xcb(); + return aznew XcbNativeWindow(); #elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND #error "Linux Window Manager Wayland not supported." return nullptr; @@ -22,5 +24,4 @@ namespace AzFramework return nullptr; #endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB } - } // namespace AzFramework diff --git a/Code/Framework/AzFramework/Platform/Linux/platform_linux.cmake b/Code/Framework/AzFramework/Platform/Linux/platform_linux.cmake index 5c8ca8392f..b08c3b310d 100644 --- a/Code/Framework/AzFramework/Platform/Linux/platform_linux.cmake +++ b/Code/Framework/AzFramework/Platform/Linux/platform_linux.cmake @@ -10,6 +10,14 @@ # Only 'xcb' and 'wayland' are recognized if (${PAL_TRAIT_LINUX_WINDOW_MANAGER} STREQUAL "xcb") + set(LY_COMPILE_DEFINITIONS PUBLIC PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB) + set(LY_INCLUDE_DIRECTORIES + PUBLIC + Platform/Common/Xcb + ) + set(LY_FILES_CMAKE + Platform/Common/Xcb/azframework_xcb_files.cmake + ) set(LY_BUILD_DEPENDENCIES PRIVATE 3rdParty::X11::xcb @@ -18,8 +26,6 @@ if (${PAL_TRAIT_LINUX_WINDOW_MANAGER} STREQUAL "xcb") 3rdParty::X11::xkbcommon_X11 ) - set(LY_COMPILE_DEFINITIONS PUBLIC PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB) - elseif(PAL_TRAIT_LINUX_WINDOW_MANAGER STREQUAL "wayland") set(LY_COMPILE_DEFINITIONS PUBLIC PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND) diff --git a/Code/Framework/AzFramework/Platform/Linux/platform_linux_files.cmake b/Code/Framework/AzFramework/Platform/Linux/platform_linux_files.cmake index 93767322b2..4f06aa5c57 100644 --- a/Code/Framework/AzFramework/Platform/Linux/platform_linux_files.cmake +++ b/Code/Framework/AzFramework/Platform/Linux/platform_linux_files.cmake @@ -12,8 +12,6 @@ set(FILES AzFramework/API/ApplicationAPI_Platform.h AzFramework/API/ApplicationAPI_Linux.h AzFramework/Application/Application_Linux.cpp - AzFramework/Application/Application_Linux_xcb.h - AzFramework/Application/Application_Linux_xcb.cpp AzFramework/Asset/AssetSystemComponentHelper_Linux.cpp AzFramework/Process/ProcessWatcher_Linux.cpp AzFramework/Process/ProcessCommon.h @@ -22,10 +20,8 @@ set(FILES ../Common/Unimplemented/AzFramework/StreamingInstall/StreamingInstall_Unimplemented.cpp ../Common/Default/AzFramework/TargetManagement/TargetManagementComponent_Default.cpp AzFramework/Windowing/NativeWindow_Linux.cpp - AzFramework/Windowing/NativeWindow_Linux_xcb.h - AzFramework/Windowing/NativeWindow_Linux_xcb.cpp ../Common/Unimplemented/AzFramework/Input/Devices/Gamepad/InputDeviceGamepad_Unimplemented.cpp - AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_xcb.cpp + AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Linux.cpp ../Common/Unimplemented/AzFramework/Input/Devices/Motion/InputDeviceMotion_Unimplemented.cpp ../Common/Unimplemented/AzFramework/Input/Devices/Mouse/InputDeviceMouse_Unimplemented.cpp ../Common/Unimplemented/AzFramework/Input/Devices/Touch/InputDeviceTouch_Unimplemented.cpp diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Linux/RHI/WSISurface_Linux.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Linux/RHI/WSISurface_Linux.cpp index a818599b0d..7d70d0245f 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Linux/RHI/WSISurface_Linux.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Linux/RHI/WSISurface_Linux.cpp @@ -10,6 +10,10 @@ #include #include +#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB +#include +#endif + namespace AZ { namespace Vulkan @@ -21,7 +25,7 @@ namespace AZ #if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB xcb_connection_t* xcb_connection = nullptr; - if (auto xcbConnectionManager = AzFramework::LinuxXcbConnectionManagerInterface::Get(); + if (auto xcbConnectionManager = AzFramework::XcbConnectionManagerInterface::Get(); xcbConnectionManager != nullptr) { xcb_connection = xcbConnectionManager->GetXcbConnection();