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 <burelc@amazon.com>
monroegm-disable-blank-issue-2
Chris Burel 4 years ago
parent 08e3d14013
commit f5effaabcc

@ -9,7 +9,7 @@
#include "QtEditorApplication.h"
#ifdef PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
#include <AzFramework/API/ApplicationAPI_Linux.h>
#include <AzFramework/XcbEventHandler.h>
#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<xcb_generic_event_t*>(message));
AzFramework::XcbEventHandlerBus::Broadcast(&AzFramework::XcbEventHandler::HandleXcbEvent, static_cast<xcb_generic_event_t*>(message));
#endif
return true;
}

@ -6,29 +6,26 @@
*
*/
#include <AzFramework/API/ApplicationAPI_Platform.h>
#include <AzFramework/Application/Application.h>
#include "Application_Linux_xcb.h"
#include <AzFramework/XcbApplication.h>
#include <AzFramework/XcbEventHandler.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
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<LinuxXcbConnectionManagerImpl>();
if (LinuxXcbConnectionManagerInterface::Get() == nullptr)
m_xcbConnectionManager = AZStd::make_unique<XcbConnectionManagerImpl>();
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

@ -5,27 +5,24 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzFramework/API/ApplicationAPI_Platform.h>
#include <AzFramework/Application/Application.h>
#include <AzFramework/XcbConnectionManager.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
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<LinuxXcbConnectionManager> m_xcbConnectionManager;
AZStd::unique_ptr<XcbConnectionManager> m_xcbConnectionManager;
};
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
} // namespace AzFramework

@ -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 <AzCore/EBus/EBus.h>
#include <AzCore/Interface/Interface.h>
#include <AzCore/RTTI/RTTI.h>
#include <xcb/xcb.h>
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<XcbConnectionManager, XcbConnectionManagerBusTraits>;
using XcbConnectionManagerInterface = AZ::Interface<XcbConnectionManager>;
} // namespace AzFramework

@ -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 <AzCore/EBus/EBus.h>
#include <AzCore/RTTI/RTTI.h>
#include <xcb/xcb.h>
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<XcbEventHandler, XcbEventHandlerBusTraits>;
} // namespace AzFramework

@ -6,9 +6,10 @@
*
*/
#include <AzCore/std/typetraits/integral_constant.h>
#include <AzFramework/API/ApplicationAPI_Linux.h>
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
#include <AzFramework/XcbEventHandler.h>
#include <AzFramework/XcbConnectionManager.h>
#include <AzFramework/XcbInputDeviceKeyboard.h>
#define explicit ExplicitIsACXXKeyword
#include <xcb/xkb.h>
@ -19,34 +20,26 @@
namespace AzFramework
{
class InputDeviceKeyboardXcb
: public InputDeviceKeyboard::Implementation
, public LinuxXcbEventHandlerBus::Handler
{
public:
AZ_CLASS_ALLOCATOR(InputDeviceKeyboardXcb, AZ::SystemAllocator, 0);
using InputDeviceKeyboard::Implementation::Implementation;
InputDeviceKeyboardXcb(InputDeviceKeyboard& inputDevice)
XcbInputDeviceKeyboard::XcbInputDeviceKeyboard(InputDeviceKeyboard& inputDevice)
: InputDeviceKeyboard::Implementation(inputDevice)
{
LinuxXcbEventHandlerBus::Handler::BusConnect();
XcbEventHandlerBus::Handler::BusConnect();
auto* interface = AzFramework::LinuxXcbConnectionManagerInterface::Get();
auto* interface = AzFramework::XcbConnectionManagerInterface::Get();
if (!interface)
{
AZ_Warning("ApplicationLinux", false, "XCB interface not available");
return;
}
auto* connection = AzFramework::LinuxXcbConnectionManagerInterface::Get()->GetXcbConnection();
auto* connection = interface->GetXcbConnection();
if (!connection)
{
AZ_Warning("ApplicationLinux", false, "XCB connection not available");
return;
}
AZStd::unique_ptr<xcb_xkb_use_extension_reply_t, DeleterForFreeFn<::std::free>> xkbUseExtensionReply{
XcbStdFreePtr<xcb_xkb_use_extension_reply_t> xkbUseExtensionReply{
xcb_xkb_use_extension_reply(connection, xcb_xkb_use_extension(connection, 1, 0), nullptr)
};
if (!xkbUseExtensionReply)
@ -69,32 +62,33 @@ namespace AzFramework
m_initialized = true;
}
bool IsConnected() const override
bool XcbInputDeviceKeyboard::IsConnected() const
{
return m_initialized;
auto* connection = AzFramework::XcbConnectionManagerInterface::Get()->GetXcbConnection();
return connection && !xcb_connection_has_error(connection);
}
bool HasTextEntryStarted() const override
bool XcbInputDeviceKeyboard::HasTextEntryStarted() const
{
return false;
}
void TextEntryStart(const InputDeviceKeyboard::VirtualKeyboardOptions& options) override
void XcbInputDeviceKeyboard::TextEntryStart(const InputDeviceKeyboard::VirtualKeyboardOptions& options)
{
}
void TextEntryStop() override
void XcbInputDeviceKeyboard::TextEntryStop()
{
}
void TickInputDevice() override
void XcbInputDeviceKeyboard::TickInputDevice()
{
ProcessRawEventQueues();
}
void HandleXcbEvent(xcb_generic_event_t* event) override
void XcbInputDeviceKeyboard::HandleXcbEvent(xcb_generic_event_t* event)
{
if (!IsConnected())
if (!m_initialized)
{
return;
}
@ -126,8 +120,7 @@ namespace AzFramework
}
}
private:
[[nodiscard]] const InputChannelId* InputChannelFromKeyEvent(xcb_keycode_t code) const
[[nodiscard]] const InputChannelId* XcbInputDeviceKeyboard::InputChannelFromKeyEvent(xcb_keycode_t code) const
{
const xcb_keysym_t keysym = xkb_state_key_get_one_sym(m_xkbState.get(), code);
@ -275,19 +268,4 @@ namespace AzFramework
default: return nullptr;
}
}
template<auto freeFn>
using DeleterForFreeFn = AZStd::integral_constant<decltype(freeFn), freeFn>;
AZStd::unique_ptr<xkb_context, DeleterForFreeFn<xkb_context_unref>> m_xkbContext;
AZStd::unique_ptr<xkb_keymap, DeleterForFreeFn<xkb_keymap_unref>> m_xkbKeymap;
AZStd::unique_ptr<xkb_state, DeleterForFreeFn<xkb_state_unref>> m_xkbState;
int m_coreDeviceId{-1};
bool m_initialized{false};
};
InputDeviceKeyboard::Implementation* InputDeviceKeyboard::Implementation::Create(InputDeviceKeyboard& inputDevice)
{
return aznew InputDeviceKeyboardXcb(inputDevice);
}
} // namespace AzFramework

@ -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 <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
#include <AzFramework/XcbEventHandler.h>
#include <AzFramework/XcbInterface.h>
#include <xcb/xcb.h>
#include <xkbcommon/xkbcommon.h>
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<xkb_context, xkb_context_unref> m_xkbContext;
XcbUniquePtr<xkb_keymap, xkb_keymap_unref> m_xkbKeymap;
XcbUniquePtr<xkb_state, xkb_state_unref> m_xkbState;
int m_coreDeviceId{-1};
bool m_initialized{false};
};
} // namespace AzFramework

@ -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 <xcb/xcb.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
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<auto Callable>
struct XcbDeleterFreeFunctionWrapper
{
using value_type = decltype(Callable);
static constexpr value_type s_value = Callable;
constexpr operator value_type() const noexcept
{
return s_value;
}
};
template<typename T, auto fn>
using XcbUniquePtr = AZStd::unique_ptr<T, XcbDeleterFreeFunctionWrapper<fn>>;
template<typename T>
using XcbStdFreePtr = XcbUniquePtr<T, ::free>;
} // namespace AzFramework

@ -6,41 +6,37 @@
*
*/
#include <AzFramework/API/ApplicationAPI_Platform.h>
#include <AzFramework/Application/Application.h>
#include <AzFramework/Windowing/NativeWindow.h>
#include <xcb/xcb.h>
#include <AzFramework/XcbNativeWindow.h>
#include <AzFramework/XcbConnectionManager.h>
#include "NativeWindow_Linux_xcb.h"
#include <xcb/xcb.h>
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<NativeWindowHandle>(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

@ -5,24 +5,25 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzFramework/API/ApplicationAPI_Platform.h>
#include <AzFramework/Application/Application.h>
#include <AzFramework/Windowing/NativeWindow.h>
#include <AzFramework/XcbEventHandler.h>
#include <xcb/xcb.h>
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

@ -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
)

@ -12,10 +12,6 @@
#include <AzCore/Interface/Interface.h>
#include <AzCore/EBus/EBus.h>
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
#include <xcb/xcb.h>
#endif // LY_COMPILE_DEFINITIONS
namespace AzFramework
{
class LinuxLifecycleEvents
@ -30,54 +26,4 @@ namespace AzFramework
using Bus = AZ::EBus<LinuxLifecycleEvents>;
};
#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<LinuxXcbConnectionManager, LinuxXcbConnectionManagerBusTraits>;
using LinuxXcbConnectionManagerInterface = AZ::Interface<LinuxXcbConnectionManager>;
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<LinuxXcbEventHandler, LinuxXcbEventHandlerBusTraits>;
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
} // namespace AzFramework

@ -8,7 +8,9 @@
#include <AzFramework/Application/Application.h>
#include "Application_Linux_xcb.h"
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
#include <AzFramework/XcbApplication.h>
#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;

@ -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 <AzFramework/XcbInputDeviceKeyboard.h>
#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

@ -6,14 +6,16 @@
*
*/
#include "NativeWindow_Linux_xcb.h"
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
#include <AzFramework/XcbNativeWindow.h>
#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

@ -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)

@ -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

@ -10,6 +10,10 @@
#include <RHI/Instance.h>
#include <RHI/WSISurface.h>
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
#include <AzFramework/XcbConnectionManager.h>
#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();

Loading…
Cancel
Save