Add support for keyboard events from xcb (#3971)

Signed-off-by: Chris Burel <burelc@amazon.com>
This commit is contained in:
Chris Burel
2021-09-20 09:09:50 -07:00
committed by GitHub
parent a4424ea820
commit 3812e60ab6
6 changed files with 324 additions and 5 deletions
+12 -2
View File
@@ -8,11 +8,21 @@
#include "QtEditorApplication.h"
#ifdef PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
#include <AzFramework/API/ApplicationAPI_Linux.h>
#endif
namespace Editor
{
bool EditorQtApplication::nativeEventFilter(const QByteArray& , void* , long* )
bool EditorQtApplication::nativeEventFilter([[maybe_unused]] const QByteArray& eventType, void* message, long*)
{
// TODO_KDAB_LINUX
if (GetIEditor()->IsInGameMode())
{
#ifdef PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
AzFramework::LinuxXcbEventHandlerBus::Broadcast(&AzFramework::LinuxXcbEventHandler::HandleXcbEvent, static_cast<xcb_generic_event_t*>(message));
#endif
return true;
}
return false;
}
}
@@ -0,0 +1,293 @@
/*
* 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 <AzCore/std/typetraits/integral_constant.h>
#include <AzFramework/API/ApplicationAPI_Linux.h>
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
#define explicit ExplicitIsACXXKeyword
#include <xcb/xkb.h>
#undef explicit
#include <xkbcommon/xkbcommon-keysyms.h>
#include <xkbcommon/xkbcommon.h>
#include <xkbcommon/xkbcommon-x11.h>
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)
: InputDeviceKeyboard::Implementation(inputDevice)
{
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<xcb_xkb_use_extension_reply_t, DeleterForFreeFn<::std::free>> 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;
}
bool IsConnected() const override
{
return m_initialized;
}
bool HasTextEntryStarted() const override
{
return false;
}
void TextEntryStart(const InputDeviceKeyboard::VirtualKeyboardOptions& options) override
{
}
void TextEntryStop() override
{
}
void TickInputDevice() override
{
ProcessRawEventQueues();
}
void HandleXcbEvent(xcb_generic_event_t* event) override
{
if (!IsConnected())
{
return;
}
switch (event->response_type & ~0x80)
{
case XCB_KEY_PRESS:
{
auto* keyPress = reinterpret_cast<xcb_key_press_event_t*>(event);
const InputChannelId* key = InputChannelFromKeyEvent(keyPress->detail);
if (key)
{
QueueRawKeyEvent(*key, true);
}
break;
}
case XCB_KEY_RELEASE:
{
auto* keyRelease = reinterpret_cast<xcb_key_release_event_t*>(event);
const InputChannelId* key = InputChannelFromKeyEvent(keyRelease->detail);
if (key)
{
QueueRawKeyEvent(*key, false);
}
break;
}
}
}
private:
[[nodiscard]] const InputChannelId* InputChannelFromKeyEvent(xcb_keycode_t code) const
{
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;
}
}
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
@@ -62,8 +62,16 @@ namespace AzFramework
uint32_t eventMask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
const uint32_t interestedEvents =
XCB_EVENT_MASK_STRUCTURE_NOTIFY
| XCB_EVENT_MASK_BUTTON_PRESS
| XCB_EVENT_MASK_BUTTON_RELEASE
| XCB_EVENT_MASK_KEY_PRESS
| XCB_EVENT_MASK_KEY_RELEASE
| XCB_EVENT_MASK_POINTER_MOTION
;
uint32_t valueList[] = { xcbRootScreen->black_pixel,
XCB_EVENT_MASK_STRUCTURE_NOTIFY };
interestedEvents };
xcb_void_cookie_t xcbCheckResult;
@@ -11,10 +11,16 @@
if (${PAL_TRAIT_LINUX_WINDOW_MANAGER} STREQUAL "xcb")
find_library(XCB_LIBRARY xcb)
find_library(XCB_XKB_LIBRARY xcb-xkb)
find_library(XKBCOMMON_LIBRARY xkbcommon)
find_library(XKBCOMMON_X11_LIBRARY xkbcommon-x11)
set(LY_BUILD_DEPENDENCIES
PRIVATE
${XCB_LIBRARY}
${XKBCOMMON_LIBRARY}
${XKBCOMMON_X11_LIBRARY}
${XCB_XKB_LIBRARY}
)
set(LY_COMPILE_DEFINITIONS PUBLIC PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB)
@@ -25,7 +25,7 @@ set(FILES
AzFramework/Windowing/NativeWindow_Linux_xcb.h
AzFramework/Windowing/NativeWindow_Linux_xcb.cpp
../Common/Unimplemented/AzFramework/Input/Devices/Gamepad/InputDeviceGamepad_Unimplemented.cpp
../Common/Unimplemented/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Unimplemented.cpp
AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_xcb.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