Remove banan-os's LibInput dependency
Platforms now define their own keymaps
This commit is contained in:
@@ -8,8 +8,6 @@
|
||||
#include "SafeGetters.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include <LibInput/KeyEvent.h>
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
@@ -2899,8 +2897,19 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
||||
dprintln(" firstKeyCode: {}", request.firstKeyCode);
|
||||
dprintln(" count: {}", request.count);
|
||||
|
||||
ASSERT(g_keymap_min_keycode <= request.firstKeyCode);
|
||||
ASSERT(g_keymap_max_keycode >= request.firstKeyCode + request.count - 1);
|
||||
if (request.firstKeyCode < g_keymap_min_keycode || request.firstKeyCode + request.count - 1 > g_keymap_max_keycode)
|
||||
{
|
||||
xError error {
|
||||
.type = X_Error,
|
||||
.errorCode = BadValue,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.resourceID = 0, // TODO: should this be something meaningful?
|
||||
.minorCode = 0,
|
||||
.majorCode = opcode,
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, error));
|
||||
break;
|
||||
}
|
||||
|
||||
xGetKeyboardMappingReply reply {
|
||||
.type = X_Reply,
|
||||
@@ -2909,10 +2918,10 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
||||
.length = static_cast<CARD32>(request.count * g_keymap_layers),
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, reply));
|
||||
|
||||
for (size_t i = 0; i < request.count; i++)
|
||||
for (size_t j = 0; j < g_keymap_layers; j++)
|
||||
TRY(encode<CARD32>(client_info.output_buffer, g_keymap[request.firstKeyCode + i][j]));
|
||||
TRY(encode(client_info.output_buffer, BAN::Span(
|
||||
g_keymap + request.firstKeyCode - g_keymap_min_keycode,
|
||||
request.count
|
||||
)));
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -2953,36 +2962,12 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
||||
|
||||
xGetModifierMappingReply reply {
|
||||
.type = X_Reply,
|
||||
.numKeyPerModifier = 2,
|
||||
.numKeyPerModifier = g_modifier_layers,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = 4,
|
||||
.length = 2 * g_modifier_layers,
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, reply));
|
||||
|
||||
using LibInput::keycode_normal;
|
||||
|
||||
// shift
|
||||
TRY(encode(client_info.output_buffer, keycode_normal(3, 0))); // lshift
|
||||
TRY(encode(client_info.output_buffer, keycode_normal(3, 12))); // rshift
|
||||
|
||||
// lock
|
||||
TRY(encode(client_info.output_buffer, keycode_normal(2, 0))); // caps lock
|
||||
TRY(encode(client_info.output_buffer, static_cast<uint8_t>(0)));
|
||||
|
||||
// control
|
||||
TRY(encode(client_info.output_buffer, keycode_normal(4, 0))); // lcrtl
|
||||
TRY(encode(client_info.output_buffer, keycode_normal(4, 6))); // rctrl
|
||||
|
||||
// mod1
|
||||
TRY(encode(client_info.output_buffer, keycode_normal(4, 2))); // lalt
|
||||
TRY(encode(client_info.output_buffer, keycode_normal(4, 5))); // ralt
|
||||
|
||||
// mod2 -> mod5
|
||||
for (size_t i = 2; i <= 5; i++)
|
||||
{
|
||||
TRY(encode(client_info.output_buffer, static_cast<uint8_t>(0)));
|
||||
TRY(encode(client_info.output_buffer, static_cast<uint8_t>(0)));
|
||||
}
|
||||
TRY(encode(client_info.output_buffer, g_modifier_map));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -38,10 +38,10 @@ endif()
|
||||
add_executable(xbanan ${XBANAN_SOURCES})
|
||||
banan_link_library(xbanan ban)
|
||||
banan_link_library(xbanan libdeflate)
|
||||
banan_link_library(xbanan libinput)
|
||||
|
||||
if(PLATFORM STREQUAL "banan-os")
|
||||
banan_link_library(xbanan libgui)
|
||||
banan_link_library(xbanan libinput)
|
||||
elseif(PLATFORM STREQUAL "SDL3")
|
||||
find_package(SDL3 REQUIRED)
|
||||
banan_link_library(xbanan SDL3::SDL3)
|
||||
|
||||
@@ -553,19 +553,16 @@ void on_mouse_button_event(WINDOW wid, uint8_t xbutton, bool pressed)
|
||||
void on_key_event(WINDOW wid, uint8_t scancode, uint8_t xmod, bool pressed)
|
||||
{
|
||||
const uint8_t xkeycode = scancode + g_keymap_min_keycode;
|
||||
if (xkeycode < g_keymap_min_keycode)
|
||||
{
|
||||
dwarnln("cannot send keycode {}", xkeycode);
|
||||
if (xkeycode < g_keymap_min_keycode || xkeycode > g_keymap_max_keycode)
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
const uint8_t byte = xkeycode / 8;
|
||||
const uint8_t bit = xkeycode % 8;
|
||||
const uint8_t byte = xkeycode / 8;
|
||||
const uint8_t mask = 1 << (xkeycode % 8);
|
||||
if (pressed)
|
||||
g_pressed_keys[byte] |= 1 << bit;
|
||||
g_pressed_keys[byte] |= mask;
|
||||
else
|
||||
g_pressed_keys[byte] &= ~(1 << bit);
|
||||
g_pressed_keys[byte] &= ~mask;
|
||||
}
|
||||
|
||||
const auto old_state = g_keymask | g_butmask;
|
||||
@@ -580,3 +577,26 @@ void on_key_event(WINDOW wid, uint8_t scancode, uint8_t xmod, bool pressed)
|
||||
old_state
|
||||
);
|
||||
}
|
||||
|
||||
void on_keymap_changed()
|
||||
{
|
||||
for (auto& [id, object] : g_objects)
|
||||
{
|
||||
if (object->type != Object::Type::Window)
|
||||
continue;
|
||||
|
||||
auto& client_info = object->object.get<Object::Window>().owner;
|
||||
|
||||
xEvent event {};
|
||||
event.u.u.type = MappingNotify;
|
||||
event.u.u.sequenceNumber = client_info.sequence;
|
||||
|
||||
event.u.mappingNotify.request = MappingKeyboard,
|
||||
event.u.mappingNotify.firstKeyCode = g_keymap_min_keycode,
|
||||
event.u.mappingNotify.count = g_keymap_size,
|
||||
MUST(encode(client_info.output_buffer, event));
|
||||
|
||||
event.u.mappingNotify.request = MappingModifier;
|
||||
MUST(encode(client_info.output_buffer, event));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,3 +15,5 @@ void on_window_leave_event(WINDOW wid);
|
||||
void on_mouse_move_event(WINDOW wid, int32_t x, int32_t y);
|
||||
void on_mouse_button_event(WINDOW wid, uint8_t xbutton, bool pressed);
|
||||
void on_key_event(WINDOW wid, uint8_t scancode, uint8_t xmod, bool pressed);
|
||||
|
||||
void on_keymap_changed();
|
||||
|
||||
@@ -1,349 +1,5 @@
|
||||
#include "Keymap.h"
|
||||
|
||||
#include <BAN/StringView.h>
|
||||
|
||||
#include <LibInput/KeyboardLayout.h>
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/XF86keysym.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#undef None
|
||||
|
||||
uint32_t g_keymap[0x100][g_keymap_layers];
|
||||
|
||||
uint32_t g_keymap[g_keymap_size][g_keymap_layers] {};
|
||||
uint8_t g_modifier_map[8][2] {};
|
||||
uint8_t g_pressed_keys[32] {};
|
||||
|
||||
static constexpr uint32_t my_key_to_x_keysym(LibInput::Key key)
|
||||
{
|
||||
using LibInput::Key;
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case Key::A:
|
||||
return XK_A;
|
||||
case Key::B:
|
||||
return XK_B;
|
||||
case Key::C:
|
||||
return XK_C;
|
||||
case Key::D:
|
||||
return XK_D;
|
||||
case Key::E:
|
||||
return XK_E;
|
||||
case Key::F:
|
||||
return XK_F;
|
||||
case Key::G:
|
||||
return XK_G;
|
||||
case Key::H:
|
||||
return XK_H;
|
||||
case Key::I:
|
||||
return XK_I;
|
||||
case Key::J:
|
||||
return XK_J;
|
||||
case Key::K:
|
||||
return XK_K;
|
||||
case Key::L:
|
||||
return XK_L;
|
||||
case Key::M:
|
||||
return XK_M;
|
||||
case Key::N:
|
||||
return XK_N;
|
||||
case Key::O:
|
||||
return XK_O;
|
||||
case Key::P:
|
||||
return XK_P;
|
||||
case Key::Q:
|
||||
return XK_Q;
|
||||
case Key::R:
|
||||
return XK_R;
|
||||
case Key::S:
|
||||
return XK_S;
|
||||
case Key::T:
|
||||
return XK_T;
|
||||
case Key::U:
|
||||
return XK_U;
|
||||
case Key::V:
|
||||
return XK_V;
|
||||
case Key::W:
|
||||
return XK_W;
|
||||
case Key::X:
|
||||
return XK_X;
|
||||
case Key::Y:
|
||||
return XK_Y;
|
||||
case Key::Z:
|
||||
return XK_Z;
|
||||
case Key::A_Ring:
|
||||
return XK_Aring;
|
||||
case Key::A_Umlaut:
|
||||
return XK_Adiaeresis;
|
||||
case Key::O_Umlaut:
|
||||
return XK_Odiaeresis;
|
||||
case Key::_0:
|
||||
return XK_0;
|
||||
case Key::_1:
|
||||
return XK_1;
|
||||
case Key::_2:
|
||||
return XK_2;
|
||||
case Key::_3:
|
||||
return XK_3;
|
||||
case Key::_4:
|
||||
return XK_4;
|
||||
case Key::_5:
|
||||
return XK_5;
|
||||
case Key::_6:
|
||||
return XK_6;
|
||||
case Key::_7:
|
||||
return XK_7;
|
||||
case Key::_8:
|
||||
return XK_8;
|
||||
case Key::_9:
|
||||
return XK_9;
|
||||
case Key::F1:
|
||||
return XK_F1;
|
||||
case Key::F2:
|
||||
return XK_F2;
|
||||
case Key::F3:
|
||||
return XK_F3;
|
||||
case Key::F4:
|
||||
return XK_F4;
|
||||
case Key::F5:
|
||||
return XK_F5;
|
||||
case Key::F6:
|
||||
return XK_F6;
|
||||
case Key::F7:
|
||||
return XK_F7;
|
||||
case Key::F8:
|
||||
return XK_F8;
|
||||
case Key::F9:
|
||||
return XK_F9;
|
||||
case Key::F10:
|
||||
return XK_F10;
|
||||
case Key::F11:
|
||||
return XK_F11;
|
||||
case Key::F12:
|
||||
return XK_F12;
|
||||
case Key::Insert:
|
||||
return XK_Insert;
|
||||
case Key::PrintScreen:
|
||||
return XK_Print;
|
||||
case Key::Delete:
|
||||
return XK_Delete;
|
||||
case Key::Home:
|
||||
return XK_Home;
|
||||
case Key::End:
|
||||
return XK_End;
|
||||
case Key::PageUp:
|
||||
return XK_Page_Up;
|
||||
case Key::PageDown:
|
||||
return XK_Page_Down;
|
||||
case Key::Enter:
|
||||
return XK_Return;
|
||||
case Key::Space:
|
||||
return XK_space;
|
||||
case Key::ExclamationMark:
|
||||
return XK_exclam;
|
||||
case Key::DoubleQuote:
|
||||
return XK_quotedbl;
|
||||
case Key::Hashtag:
|
||||
return XK_numbersign;
|
||||
case Key::Currency:
|
||||
return XK_currency;
|
||||
case Key::Percent:
|
||||
return XK_percent;
|
||||
case Key::Ampersand:
|
||||
return XK_ampersand;
|
||||
case Key::Slash:
|
||||
return XK_slash;
|
||||
case Key::Section:
|
||||
return XK_section;
|
||||
case Key::Half:
|
||||
return XK_onehalf;
|
||||
case Key::OpenParenthesis:
|
||||
return '(';
|
||||
case Key::CloseParenthesis:
|
||||
return ')';
|
||||
case Key::OpenSquareBracket:
|
||||
return '[';
|
||||
case Key::CloseSquareBracket:
|
||||
return ']';
|
||||
case Key::OpenCurlyBracket:
|
||||
return '{';
|
||||
case Key::CloseCurlyBracket:
|
||||
return '}';
|
||||
case Key::Equals:
|
||||
return '=';
|
||||
case Key::QuestionMark:
|
||||
return '?';
|
||||
case Key::Plus:
|
||||
return '+';
|
||||
case Key::BackSlash:
|
||||
return '\\';
|
||||
case Key::Acute:
|
||||
return XK_acute;
|
||||
case Key::BackTick:
|
||||
return '`';
|
||||
case Key::TwoDots:
|
||||
return XK_diaeresis;
|
||||
case Key::Cedilla:
|
||||
return XK_Ccedilla;
|
||||
case Key::Backspace:
|
||||
return XK_BackSpace;
|
||||
case Key::AtSign:
|
||||
return XK_at;
|
||||
case Key::Pound:
|
||||
return XK_sterling;
|
||||
case Key::Dollar:
|
||||
return XK_dollar;
|
||||
case Key::Euro:
|
||||
return XK_EuroSign;
|
||||
case Key::Escape:
|
||||
return XK_Escape;
|
||||
case Key::Tab:
|
||||
return XK_Tab;
|
||||
case Key::CapsLock:
|
||||
return XK_Caps_Lock;
|
||||
case Key::LeftShift:
|
||||
return XK_Shift_L;
|
||||
case Key::LeftCtrl:
|
||||
return XK_Control_L;
|
||||
case Key::Super:
|
||||
return XK_Super_L;
|
||||
case Key::LeftAlt:
|
||||
return XK_Alt_L;
|
||||
case Key::RightAlt:
|
||||
return XK_Alt_R;
|
||||
case Key::RightCtrl:
|
||||
return XK_Control_R;
|
||||
case Key::RightShift:
|
||||
return XK_Shift_R;
|
||||
case Key::SingleQuote:
|
||||
return '\'';
|
||||
case Key::Asterix:
|
||||
return '*';
|
||||
case Key::Caret:
|
||||
return '^';
|
||||
case Key::Tilde:
|
||||
return '~';
|
||||
case Key::ArrowUp:
|
||||
return XK_Up;
|
||||
case Key::ArrowDown:
|
||||
return XK_Down;
|
||||
case Key::ArrowLeft:
|
||||
return XK_Left;
|
||||
case Key::ArrowRight:
|
||||
return XK_Right;
|
||||
case Key::Comma:
|
||||
return ',';
|
||||
case Key::Semicolon:
|
||||
return ';';
|
||||
case Key::Period:
|
||||
return '.';
|
||||
case Key::Colon:
|
||||
return ':';
|
||||
case Key::Hyphen:
|
||||
return '-';
|
||||
case Key::Underscore:
|
||||
return '_';
|
||||
case Key::NumLock:
|
||||
return XK_Num_Lock;
|
||||
case Key::ScrollLock:
|
||||
return XK_Scroll_Lock;
|
||||
case Key::LessThan:
|
||||
return '<';
|
||||
case Key::GreaterThan:
|
||||
return '>';
|
||||
case Key::Pipe:
|
||||
return '|';
|
||||
case Key::Negation:
|
||||
return XK_notsign;
|
||||
case Key::BrokenBar:
|
||||
return XK_brokenbar;
|
||||
case Key::Numpad0:
|
||||
return XK_KP_0;
|
||||
case Key::Numpad1:
|
||||
return XK_KP_1;
|
||||
case Key::Numpad2:
|
||||
return XK_KP_2;
|
||||
case Key::Numpad3:
|
||||
return XK_KP_3;
|
||||
case Key::Numpad4:
|
||||
return XK_KP_4;
|
||||
case Key::Numpad5:
|
||||
return XK_KP_5;
|
||||
case Key::Numpad6:
|
||||
return XK_KP_6;
|
||||
case Key::Numpad7:
|
||||
return XK_KP_7;
|
||||
case Key::Numpad8:
|
||||
return XK_KP_8;
|
||||
case Key::Numpad9:
|
||||
return XK_KP_9;
|
||||
case Key::NumpadPlus:
|
||||
return XK_KP_Add;
|
||||
case Key::NumpadMinus:
|
||||
return XK_KP_Subtract;
|
||||
case Key::NumpadMultiply:
|
||||
return XK_KP_Multiply;
|
||||
case Key::NumpadDivide:
|
||||
return XK_KP_Divide;
|
||||
case Key::NumpadEnter:
|
||||
return XK_KP_Enter;
|
||||
case Key::NumpadDecimal:
|
||||
return XK_KP_Decimal;
|
||||
case Key::VolumeMute:
|
||||
return XF86XK_AudioMute;
|
||||
case Key::VolumeUp:
|
||||
return XF86XK_AudioRaiseVolume;
|
||||
case Key::VolumeDown:
|
||||
return XF86XK_AudioLowerVolume;
|
||||
case Key::Calculator:
|
||||
return XF86XK_Calculator;
|
||||
case Key::MediaPlayPause:
|
||||
return XF86XK_AudioPlay;
|
||||
case Key::MediaStop:
|
||||
return XF86XK_AudioStop;
|
||||
case Key::MediaPrevious:
|
||||
return XF86XK_AudioPrev;
|
||||
case Key::MediaNext:
|
||||
return XF86XK_AudioNext;
|
||||
|
||||
case Key::Invalid:
|
||||
case Key::None:
|
||||
case Key::Count:
|
||||
break;
|
||||
}
|
||||
|
||||
return NoSymbol;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> initialize_keymap()
|
||||
{
|
||||
for (auto& keycode : g_keymap)
|
||||
for (auto& keysym : keycode)
|
||||
keysym = NoSymbol;
|
||||
|
||||
// FIXME: get this from somewhere (gui command? enviroment? tmp file?)
|
||||
const auto keymap_path = "./us.keymap"_sv;
|
||||
|
||||
TRY(LibInput::KeyboardLayout::initialize());
|
||||
|
||||
auto& keyboard_layout = LibInput::KeyboardLayout::get();
|
||||
TRY(keyboard_layout.load_from_file(keymap_path));
|
||||
|
||||
const BAN::Span<const LibInput::Key> my_keymaps[] {
|
||||
keyboard_layout.keymap_normal(),
|
||||
keyboard_layout.keymap_shift(),
|
||||
keyboard_layout.keymap_altgr(),
|
||||
keyboard_layout.keymap_altgr(), // add shift+altgr map?
|
||||
};
|
||||
|
||||
for (size_t keycode = g_keymap_min_keycode; keycode < g_keymap_max_keycode; keycode++)
|
||||
for (size_t layer = 0; layer < g_keymap_layers; layer++)
|
||||
if (auto my_key = my_keymaps[layer][keycode - g_keymap_min_keycode]; my_key != LibInput::Key::None)
|
||||
if (auto keysym = my_key_to_x_keysym(my_key); keysym != NoSymbol)
|
||||
g_keymap[keycode][layer] = (layer % 2) ? toupper(keysym) : tolower(keysym);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <BAN/Errors.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
BAN::ErrorOr<void> initialize_keymap();
|
||||
|
||||
constexpr size_t g_keymap_min_keycode = 8;
|
||||
constexpr size_t g_keymap_max_keycode = 255;
|
||||
constexpr size_t g_keymap_size = g_keymap_max_keycode - g_keymap_min_keycode + 1;
|
||||
|
||||
constexpr size_t g_keymap_layers = 4;
|
||||
extern uint32_t g_keymap[0x100][g_keymap_layers];
|
||||
extern uint32_t g_keymap[g_keymap_size][g_keymap_layers];
|
||||
|
||||
// shift, capslock, control, alt, numlock, level5 shift, super, altgr with 2 keycodes per modifier
|
||||
constexpr size_t g_modifier_layers = 2;
|
||||
extern uint8_t g_modifier_map[8][g_modifier_layers];
|
||||
|
||||
extern uint8_t g_pressed_keys[32];
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../Events.h"
|
||||
#include "../Keymap.h"
|
||||
#include "../Platform.h"
|
||||
|
||||
#include <BAN/Atomic.h>
|
||||
@@ -52,13 +53,6 @@ struct SDLCursor final : public PlatformCursor
|
||||
|
||||
static int s_eventfd { -1 };
|
||||
|
||||
struct Keymap
|
||||
{
|
||||
consteval Keymap();
|
||||
uint8_t map[SDL_SCANCODE_COUNT];
|
||||
};
|
||||
static Keymap s_sdl_keymap;
|
||||
|
||||
static SDL_Cursor* s_default_cursor { nullptr };
|
||||
|
||||
static void* sdl3_thread(void*)
|
||||
@@ -73,6 +67,8 @@ static void* sdl3_thread(void*)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void sdl3_initialize_keymap();
|
||||
|
||||
static bool sdl3_initialize(uint32_t* display_w, uint32_t* display_h)
|
||||
{
|
||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS))
|
||||
@@ -92,6 +88,8 @@ static bool sdl3_initialize(uint32_t* display_w, uint32_t* display_h)
|
||||
*display_h = BAN::Math::max<uint32_t>(*display_h, rect.y + rect.h);
|
||||
}
|
||||
|
||||
sdl3_initialize_keymap();
|
||||
|
||||
s_default_cursor = SDL_GetCursor();
|
||||
|
||||
s_eventfd = eventfd(0, 0);
|
||||
@@ -270,23 +268,25 @@ static void sdl3_poll_events(void*)
|
||||
case SDL_EVENT_KEY_UP:
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
{
|
||||
uint8_t scancode = s_sdl_keymap.map[event.key.scancode];
|
||||
|
||||
uint8_t xmod { 0 };
|
||||
if (event.key.mod & SDL_KMOD_SHIFT)
|
||||
xmod |= (1 << 0);
|
||||
if (event.key.mod & SDL_KMOD_CAPS)
|
||||
xmod |= (1 << 1);
|
||||
if (event.key.mod & SDL_KMOD_CTRL)
|
||||
xmod |= (1 << 2);
|
||||
if (event.key.mod & SDL_KMOD_ALT)
|
||||
xmod |= (1 << 3);
|
||||
const uint8_t xmod =
|
||||
((event.key.mod & SDL_KMOD_SHIFT) ? (1 << 0) : 0) |
|
||||
((event.key.mod & SDL_KMOD_CAPS) ? (1 << 1) : 0) |
|
||||
((event.key.mod & SDL_KMOD_CTRL) ? (1 << 2) : 0) |
|
||||
((event.key.mod & SDL_KMOD_ALT) ? (1 << 3) : 0) |
|
||||
((event.key.mod & SDL_KMOD_NUM) ? (1 << 4) : 0) |
|
||||
((event.key.mod & SDL_KMOD_LEVEL5) ? (1 << 5) : 0) |
|
||||
((event.key.mod & SDL_KMOD_GUI) ? (1 << 6) : 0) |
|
||||
((event.key.mod & SDL_KMOD_MODE) ? (1 << 7) : 0);
|
||||
|
||||
auto it = s_window_map.find(event.window.windowID);
|
||||
if (it != s_window_map.end())
|
||||
on_key_event(it->value->wid, scancode, xmod, (event.type == SDL_EVENT_KEY_DOWN));
|
||||
on_key_event(it->value->wid, event.key.scancode, xmod, (event.type == SDL_EVENT_KEY_DOWN));
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_KEYMAP_CHANGED:
|
||||
sdl3_initialize_keymap();
|
||||
on_keymap_changed();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -449,124 +449,255 @@ PlatformOps g_platform_ops = {
|
||||
.set_cursor = sdl3_set_cursor,
|
||||
};
|
||||
|
||||
#include <LibInput/KeyEvent.h>
|
||||
static uint32_t sdl3_keycode_to_x_keysym(SDL_Keycode keycode);
|
||||
|
||||
consteval Keymap::Keymap()
|
||||
static void sdl3_initialize_keymap()
|
||||
{
|
||||
for (auto& scancode : map)
|
||||
scancode = 0;
|
||||
static constexpr SDL_Keymod modifier_map[] {
|
||||
SDL_KMOD_NONE,
|
||||
SDL_KMOD_SHIFT,
|
||||
SDL_KMOD_MODE,
|
||||
SDL_KMOD_MODE | SDL_KMOD_SHIFT,
|
||||
};
|
||||
|
||||
using LibInput::keycode_normal;
|
||||
using LibInput::keycode_function;
|
||||
using LibInput::keycode_numpad;
|
||||
memset(g_keymap, 0, sizeof(g_keymap));
|
||||
memset(g_modifier_map, 0, sizeof(g_modifier_map));
|
||||
|
||||
map[SDL_SCANCODE_GRAVE] = keycode_normal(0, 0);
|
||||
map[SDL_SCANCODE_1] = keycode_normal(0, 1);
|
||||
map[SDL_SCANCODE_2] = keycode_normal(0, 2);
|
||||
map[SDL_SCANCODE_3] = keycode_normal(0, 3);
|
||||
map[SDL_SCANCODE_4] = keycode_normal(0, 4);
|
||||
map[SDL_SCANCODE_5] = keycode_normal(0, 5);
|
||||
map[SDL_SCANCODE_6] = keycode_normal(0, 6);
|
||||
map[SDL_SCANCODE_7] = keycode_normal(0, 7);
|
||||
map[SDL_SCANCODE_8] = keycode_normal(0, 8);
|
||||
map[SDL_SCANCODE_9] = keycode_normal(0, 9);
|
||||
map[SDL_SCANCODE_0] = keycode_normal(0, 10);
|
||||
map[SDL_SCANCODE_MINUS] = keycode_normal(0, 11);
|
||||
map[SDL_SCANCODE_EQUALS] = keycode_normal(0, 12);
|
||||
map[SDL_SCANCODE_BACKSPACE] = keycode_normal(0, 13);
|
||||
for (size_t scancode = 0; scancode < g_keymap_size; scancode++)
|
||||
for (size_t layer = 0; layer < g_keymap_layers; layer++)
|
||||
if (const auto sdl_key = SDL_GetKeyFromScancode(static_cast<SDL_Scancode>(scancode), modifier_map[layer], false); sdl_key != SDLK_UNKNOWN)
|
||||
g_keymap[scancode][layer] = sdl3_keycode_to_x_keysym(sdl_key);
|
||||
|
||||
map[SDL_SCANCODE_TAB] = keycode_normal(1, 0);
|
||||
map[SDL_SCANCODE_Q] = keycode_normal(1, 1);
|
||||
map[SDL_SCANCODE_W] = keycode_normal(1, 2);
|
||||
map[SDL_SCANCODE_E] = keycode_normal(1, 3);
|
||||
map[SDL_SCANCODE_R] = keycode_normal(1, 4);
|
||||
map[SDL_SCANCODE_T] = keycode_normal(1, 5);
|
||||
map[SDL_SCANCODE_Y] = keycode_normal(1, 6);
|
||||
map[SDL_SCANCODE_U] = keycode_normal(1, 7);
|
||||
map[SDL_SCANCODE_I] = keycode_normal(1, 8);
|
||||
map[SDL_SCANCODE_O] = keycode_normal(1, 9);
|
||||
map[SDL_SCANCODE_P] = keycode_normal(1, 10);
|
||||
map[SDL_SCANCODE_LEFTBRACKET] = keycode_normal(1, 11);
|
||||
map[SDL_SCANCODE_RIGHTBRACKET] = keycode_normal(1, 12);
|
||||
const auto get_scancode = [](SDL_Keycode keycode) -> uint8_t {
|
||||
const auto scancode = SDL_GetScancodeFromKey(keycode, nullptr);;
|
||||
if (scancode != SDL_SCANCODE_UNKNOWN && scancode < g_keymap_size)
|
||||
return scancode + g_keymap_min_keycode;
|
||||
return 0;
|
||||
};
|
||||
|
||||
map[SDL_SCANCODE_CAPSLOCK] = keycode_normal(2, 0);
|
||||
map[SDL_SCANCODE_A] = keycode_normal(2, 1);
|
||||
map[SDL_SCANCODE_S] = keycode_normal(2, 2);
|
||||
map[SDL_SCANCODE_D] = keycode_normal(2, 3);
|
||||
map[SDL_SCANCODE_F] = keycode_normal(2, 4);
|
||||
map[SDL_SCANCODE_G] = keycode_normal(2, 5);
|
||||
map[SDL_SCANCODE_H] = keycode_normal(2, 6);
|
||||
map[SDL_SCANCODE_J] = keycode_normal(2, 7);
|
||||
map[SDL_SCANCODE_K] = keycode_normal(2, 8);
|
||||
map[SDL_SCANCODE_L] = keycode_normal(2, 9);
|
||||
map[SDL_SCANCODE_SEMICOLON] = keycode_normal(2, 10);
|
||||
map[SDL_SCANCODE_APOSTROPHE] = keycode_normal(2, 11);
|
||||
map[SDL_SCANCODE_BACKSLASH] = keycode_normal(2, 12);
|
||||
map[SDL_SCANCODE_RETURN] = keycode_normal(2, 13);
|
||||
g_modifier_map[0][0] = get_scancode(SDLK_LSHIFT);
|
||||
g_modifier_map[0][1] = get_scancode(SDLK_RSHIFT);
|
||||
|
||||
map[SDL_SCANCODE_LSHIFT] = keycode_normal(3, 0);
|
||||
map[SDL_SCANCODE_NONUSBACKSLASH] = keycode_normal(3, 1);
|
||||
map[SDL_SCANCODE_Z] = keycode_normal(3, 2);
|
||||
map[SDL_SCANCODE_X] = keycode_normal(3, 3);
|
||||
map[SDL_SCANCODE_C] = keycode_normal(3, 4);
|
||||
map[SDL_SCANCODE_V] = keycode_normal(3, 5);
|
||||
map[SDL_SCANCODE_B] = keycode_normal(3, 6);
|
||||
map[SDL_SCANCODE_N] = keycode_normal(3, 7);
|
||||
map[SDL_SCANCODE_M] = keycode_normal(3, 8);
|
||||
map[SDL_SCANCODE_COMMA] = keycode_normal(3, 9);
|
||||
map[SDL_SCANCODE_PERIOD] = keycode_normal(3, 10);
|
||||
map[SDL_SCANCODE_SLASH] = keycode_normal(3, 11);
|
||||
map[SDL_SCANCODE_RSHIFT] = keycode_normal(3, 12);
|
||||
g_modifier_map[1][0] = get_scancode(SDLK_CAPSLOCK);
|
||||
|
||||
map[SDL_SCANCODE_LCTRL] = keycode_normal(4, 0);
|
||||
map[SDL_SCANCODE_LGUI] = keycode_normal(4, 1);
|
||||
map[SDL_SCANCODE_LALT] = keycode_normal(4, 2);
|
||||
map[SDL_SCANCODE_SPACE] = keycode_normal(4, 3);
|
||||
map[SDL_SCANCODE_RALT] = keycode_normal(4, 4);
|
||||
map[SDL_SCANCODE_RCTRL] = keycode_normal(4, 5);
|
||||
g_modifier_map[2][0] = get_scancode(SDLK_LCTRL);
|
||||
g_modifier_map[2][1] = get_scancode(SDLK_RCTRL);
|
||||
|
||||
map[SDL_SCANCODE_UP] = keycode_normal(5, 0);
|
||||
map[SDL_SCANCODE_LEFT] = keycode_normal(5, 1);
|
||||
map[SDL_SCANCODE_DOWN] = keycode_normal(5, 2);
|
||||
map[SDL_SCANCODE_RIGHT] = keycode_normal(5, 3);
|
||||
g_modifier_map[3][0] = get_scancode(SDLK_LALT);
|
||||
g_modifier_map[3][1] = get_scancode(SDLK_RALT);
|
||||
|
||||
map[SDL_SCANCODE_ESCAPE] = keycode_function(0);
|
||||
map[SDL_SCANCODE_F1] = keycode_function(1);
|
||||
map[SDL_SCANCODE_F2] = keycode_function(2);
|
||||
map[SDL_SCANCODE_F3] = keycode_function(3);
|
||||
map[SDL_SCANCODE_F4] = keycode_function(4);
|
||||
map[SDL_SCANCODE_F5] = keycode_function(5);
|
||||
map[SDL_SCANCODE_F6] = keycode_function(6);
|
||||
map[SDL_SCANCODE_F7] = keycode_function(7);
|
||||
map[SDL_SCANCODE_F8] = keycode_function(8);
|
||||
map[SDL_SCANCODE_F9] = keycode_function(9);
|
||||
map[SDL_SCANCODE_F10] = keycode_function(10);
|
||||
map[SDL_SCANCODE_F11] = keycode_function(11);
|
||||
map[SDL_SCANCODE_F12] = keycode_function(12);
|
||||
map[SDL_SCANCODE_INSERT] = keycode_function(13);
|
||||
map[SDL_SCANCODE_PRINTSCREEN] = keycode_function(14);
|
||||
map[SDL_SCANCODE_DELETE] = keycode_function(15);
|
||||
map[SDL_SCANCODE_HOME] = keycode_function(16);
|
||||
map[SDL_SCANCODE_END] = keycode_function(17);
|
||||
map[SDL_SCANCODE_PAGEUP] = keycode_function(18);
|
||||
map[SDL_SCANCODE_PAGEDOWN] = keycode_function(19);
|
||||
map[SDL_SCANCODE_SCROLLLOCK] = keycode_function(20);
|
||||
g_modifier_map[4][0] = get_scancode(SDLK_NUMLOCKCLEAR);
|
||||
|
||||
map[SDL_SCANCODE_NUMLOCKCLEAR] = keycode_numpad(0, 0);
|
||||
map[SDL_SCANCODE_KP_DIVIDE] = keycode_numpad(0, 1);
|
||||
map[SDL_SCANCODE_KP_MULTIPLY] = keycode_numpad(0, 2);
|
||||
map[SDL_SCANCODE_KP_MINUS] = keycode_numpad(0, 3);
|
||||
map[SDL_SCANCODE_KP_7] = keycode_numpad(1, 0);
|
||||
map[SDL_SCANCODE_KP_8] = keycode_numpad(1, 1);
|
||||
map[SDL_SCANCODE_KP_9] = keycode_numpad(1, 2);
|
||||
map[SDL_SCANCODE_KP_PLUS] = keycode_numpad(1, 3);
|
||||
map[SDL_SCANCODE_KP_4] = keycode_numpad(2, 0);
|
||||
map[SDL_SCANCODE_KP_5] = keycode_numpad(2, 1);
|
||||
map[SDL_SCANCODE_KP_6] = keycode_numpad(2, 2);
|
||||
map[SDL_SCANCODE_KP_1] = keycode_numpad(3, 0);
|
||||
map[SDL_SCANCODE_KP_2] = keycode_numpad(3, 1);
|
||||
map[SDL_SCANCODE_KP_3] = keycode_numpad(3, 2);
|
||||
map[SDL_SCANCODE_KP_ENTER] = keycode_numpad(3, 3);
|
||||
map[SDL_SCANCODE_KP_0] = keycode_numpad(4, 0);
|
||||
map[SDL_SCANCODE_KP_COMMA] = keycode_numpad(4, 1);
|
||||
};
|
||||
g_modifier_map[5][0] = get_scancode(SDLK_LEVEL5_SHIFT);
|
||||
|
||||
g_modifier_map[6][0] = get_scancode(SDLK_LGUI);
|
||||
g_modifier_map[6][1] = get_scancode(SDLK_RGUI);
|
||||
|
||||
g_modifier_map[7][0] = get_scancode(SDLK_MODE);
|
||||
}
|
||||
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/XF86keysym.h>
|
||||
|
||||
#include <wctype.h>
|
||||
|
||||
static uint32_t sdl3_keycode_to_x_keysym(SDL_Keycode keycode)
|
||||
{
|
||||
if (iswprint(keycode))
|
||||
{
|
||||
if ((keycode >= 0x20 && keycode <= 0x7E) || (keycode >= 0xA0 && keycode <= 0xFF))
|
||||
return keycode;
|
||||
return 0x01000000 | keycode;
|
||||
}
|
||||
|
||||
switch (keycode)
|
||||
{
|
||||
case SDLK_RETURN: return XK_Return;
|
||||
case SDLK_ESCAPE: return XK_Escape;
|
||||
case SDLK_BACKSPACE: return XK_BackSpace;
|
||||
case SDLK_TAB: return XK_Tab;
|
||||
case SDLK_DELETE: return XK_Delete;
|
||||
case SDLK_CAPSLOCK: return XK_Caps_Lock;
|
||||
case SDLK_F1: return XK_F1;
|
||||
case SDLK_F2: return XK_F2;
|
||||
case SDLK_F3: return XK_F3;
|
||||
case SDLK_F4: return XK_F4;
|
||||
case SDLK_F5: return XK_F5;
|
||||
case SDLK_F6: return XK_F6;
|
||||
case SDLK_F7: return XK_F7;
|
||||
case SDLK_F8: return XK_F8;
|
||||
case SDLK_F9: return XK_F9;
|
||||
case SDLK_F10: return XK_F10;
|
||||
case SDLK_F11: return XK_F11;
|
||||
case SDLK_F12: return XK_F12;
|
||||
case SDLK_PRINTSCREEN: return XK_Print;
|
||||
case SDLK_SCROLLLOCK: return XK_Scroll_Lock;
|
||||
case SDLK_PAUSE: return XK_Pause;
|
||||
case SDLK_INSERT: return XK_Insert;
|
||||
case SDLK_HOME: return XK_Home;
|
||||
case SDLK_PAGEUP: return XK_Page_Up;
|
||||
case SDLK_END: return XK_End;
|
||||
case SDLK_PAGEDOWN: return XK_Page_Down;
|
||||
case SDLK_RIGHT: return XK_Right;
|
||||
case SDLK_LEFT: return XK_Left;
|
||||
case SDLK_DOWN: return XK_Down;
|
||||
case SDLK_UP: return XK_Up;
|
||||
case SDLK_NUMLOCKCLEAR: return XK_Num_Lock;
|
||||
case SDLK_KP_DIVIDE: return XK_KP_Divide;
|
||||
case SDLK_KP_MULTIPLY: return XK_KP_Multiply;
|
||||
case SDLK_KP_MINUS: return XK_KP_Subtract;
|
||||
case SDLK_KP_PLUS: return XK_KP_Add;
|
||||
case SDLK_KP_ENTER: return XK_KP_Enter;
|
||||
case SDLK_KP_1: return XK_KP_1;
|
||||
case SDLK_KP_2: return XK_KP_2;
|
||||
case SDLK_KP_3: return XK_KP_3;
|
||||
case SDLK_KP_4: return XK_KP_4;
|
||||
case SDLK_KP_5: return XK_KP_5;
|
||||
case SDLK_KP_6: return XK_KP_6;
|
||||
case SDLK_KP_7: return XK_KP_7;
|
||||
case SDLK_KP_8: return XK_KP_8;
|
||||
case SDLK_KP_9: return XK_KP_9;
|
||||
case SDLK_KP_0: return XK_KP_0;
|
||||
case SDLK_KP_PERIOD: return XK_KP_Decimal;
|
||||
case SDLK_APPLICATION: return XF86XK_ApplicationLeft;
|
||||
case SDLK_POWER: return XF86XK_PowerOff;
|
||||
case SDLK_KP_EQUALS: return XK_KP_Equal;
|
||||
case SDLK_F13: return XK_F13;
|
||||
case SDLK_F14: return XK_F14;
|
||||
case SDLK_F15: return XK_F15;
|
||||
case SDLK_F16: return XK_F16;
|
||||
case SDLK_F17: return XK_F17;
|
||||
case SDLK_F18: return XK_F18;
|
||||
case SDLK_F19: return XK_F19;
|
||||
case SDLK_F20: return XK_F20;
|
||||
case SDLK_F21: return XK_F21;
|
||||
case SDLK_F22: return XK_F22;
|
||||
case SDLK_F23: return XK_F23;
|
||||
case SDLK_F24: return XK_F24;
|
||||
case SDLK_EXECUTE: return XK_Execute;
|
||||
case SDLK_HELP: return XK_Help;
|
||||
case SDLK_MENU: return XK_Menu;
|
||||
case SDLK_SELECT: return XK_Select;
|
||||
case SDLK_STOP: return XF86XK_Stop;
|
||||
case SDLK_AGAIN: return XK_Redo;
|
||||
case SDLK_UNDO: return XK_Undo;
|
||||
case SDLK_CUT: return XF86XK_Cut;
|
||||
case SDLK_COPY: return XF86XK_Copy;
|
||||
case SDLK_PASTE: return XF86XK_Paste;
|
||||
case SDLK_FIND: return XK_Find;
|
||||
case SDLK_MUTE: return XF86XK_AudioMute;
|
||||
case SDLK_VOLUMEUP: return XF86XK_AudioRaiseVolume;
|
||||
case SDLK_VOLUMEDOWN: return XF86XK_AudioLowerVolume;
|
||||
case SDLK_KP_COMMA: return XK_KP_Separator;
|
||||
//case SDLK_KP_EQUALSAS400: return ;
|
||||
//case SDLK_ALTERASE: return ;
|
||||
case SDLK_SYSREQ: return XK_Sys_Req;
|
||||
case SDLK_CANCEL: return XK_Cancel;
|
||||
case SDLK_CLEAR: return XK_Clear;
|
||||
case SDLK_PRIOR: return XK_Prior;
|
||||
case SDLK_RETURN2: return XK_Return;
|
||||
//case SDLK_SEPARATOR: return ;
|
||||
//case SDLK_OUT: return ;
|
||||
//case SDLK_OPER: return ;
|
||||
//case SDLK_CLEARAGAIN: return ;
|
||||
//case SDLK_CRSEL: return ;
|
||||
//case SDLK_EXSEL: return ;
|
||||
//case SDLK_KP_00: return ;
|
||||
//case SDLK_KP_000: return ;
|
||||
//case SDLK_THOUSANDSSEPARATOR: return ;
|
||||
//case SDLK_DECIMALSEPARATOR: return ;
|
||||
//case SDLK_CURRENCYUNIT: return ;
|
||||
//case SDLK_CURRENCYSUBUNIT: return ;
|
||||
//case SDLK_KP_LEFTPAREN: return ;
|
||||
//case SDLK_KP_RIGHTPAREN: return ;
|
||||
//case SDLK_KP_LEFTBRACE: return ;
|
||||
//case SDLK_KP_RIGHTBRACE: return ;
|
||||
case SDLK_KP_TAB: return XK_KP_Tab;
|
||||
//case SDLK_KP_BACKSPACE: return ;
|
||||
//case SDLK_KP_A: return ;
|
||||
//case SDLK_KP_B: return ;
|
||||
//case SDLK_KP_C: return ;
|
||||
//case SDLK_KP_D: return ;
|
||||
//case SDLK_KP_E: return ;
|
||||
//case SDLK_KP_F: return ;
|
||||
//case SDLK_KP_XOR: return ;
|
||||
//case SDLK_KP_POWER: return ;
|
||||
//case SDLK_KP_PERCENT: return ;
|
||||
//case SDLK_KP_LESS: return ;
|
||||
//case SDLK_KP_GREATER: return ;
|
||||
//case SDLK_KP_AMPERSAND: return ;
|
||||
//case SDLK_KP_DBLAMPERSAND: return ;
|
||||
//case SDLK_KP_VERTICALBAR: return ;
|
||||
//case SDLK_KP_DBLVERTICALBAR: return ;
|
||||
//case SDLK_KP_COLON: return ;
|
||||
//case SDLK_KP_HASH: return ;
|
||||
//case SDLK_KP_SPACE: return ;
|
||||
//case SDLK_KP_AT: return ;
|
||||
//case SDLK_KP_EXCLAM: return ;
|
||||
//case SDLK_KP_MEMSTORE: return ;
|
||||
//case SDLK_KP_MEMRECALL: return ;
|
||||
//case SDLK_KP_MEMCLEAR: return ;
|
||||
//case SDLK_KP_MEMADD: return ;
|
||||
//case SDLK_KP_MEMSUBTRACT: return ;
|
||||
//case SDLK_KP_MEMMULTIPLY: return ;
|
||||
//case SDLK_KP_MEMDIVIDE: return ;
|
||||
//case SDLK_KP_PLUSMINUS: return ;
|
||||
//case SDLK_KP_CLEAR: return ;
|
||||
//case SDLK_KP_CLEARENTRY: return ;
|
||||
//case SDLK_KP_BINARY: return ;
|
||||
//case SDLK_KP_OCTAL: return ;
|
||||
//case SDLK_KP_DECIMAL: return ;
|
||||
//case SDLK_KP_HEXADECIMAL: return ;
|
||||
case SDLK_LCTRL: return XK_Control_L;
|
||||
case SDLK_LSHIFT: return XK_Shift_L;
|
||||
case SDLK_LALT: return XK_Alt_L;
|
||||
case SDLK_LGUI: return XK_Super_L;
|
||||
case SDLK_RCTRL: return XK_Control_R;
|
||||
case SDLK_RSHIFT: return XK_Shift_R;
|
||||
case SDLK_RALT: return XK_Alt_R;
|
||||
case SDLK_RGUI: return XK_Super_R;
|
||||
case SDLK_MODE: return XK_Mode_switch;
|
||||
case SDLK_SLEEP: return XF86XK_Sleep;
|
||||
case SDLK_WAKE: return XF86XK_WakeUp;
|
||||
//case SDLK_CHANNEL_INCREMENT: return XF86XK_ChannelUp;
|
||||
//case SDLK_CHANNEL_DECREMENT: return XF86XK_ChannelDown;
|
||||
case SDLK_MEDIA_PLAY: return XF86XK_AudioPlay;
|
||||
case SDLK_MEDIA_PAUSE: return XF86XK_AudioPause;
|
||||
case SDLK_MEDIA_RECORD: return XF86XK_AudioRecord;
|
||||
case SDLK_MEDIA_FAST_FORWARD: return XF86XK_AudioForward;
|
||||
case SDLK_MEDIA_REWIND: return XF86XK_AudioRewind;
|
||||
case SDLK_MEDIA_NEXT_TRACK: return XF86XK_AudioNext;
|
||||
case SDLK_MEDIA_PREVIOUS_TRACK: return XF86XK_AudioPrev;
|
||||
case SDLK_MEDIA_STOP: return XF86XK_AudioStop;
|
||||
case SDLK_MEDIA_EJECT: return XF86XK_Eject;
|
||||
//case SDLK_MEDIA_PLAY_PAUSE: return XF86XK_MediaPlayPause;
|
||||
case SDLK_MEDIA_SELECT: return XF86XK_AudioMedia;
|
||||
case SDLK_AC_NEW: return XF86XK_New;
|
||||
case SDLK_AC_OPEN: return XF86XK_Open;
|
||||
case SDLK_AC_CLOSE: return XF86XK_Close;
|
||||
//case SDLK_AC_EXIT: return XF86XK_Exit;
|
||||
case SDLK_AC_SAVE: return XF86XK_Save;
|
||||
case SDLK_AC_PRINT: return XK_Print;
|
||||
//case SDLK_AC_PROPERTIES: return ;
|
||||
case SDLK_AC_SEARCH: return XF86XK_Search;
|
||||
case SDLK_AC_HOME: return XF86XK_HomePage; // ?
|
||||
case SDLK_AC_BACK: return XF86XK_Back;
|
||||
case SDLK_AC_FORWARD: return XF86XK_Forward;
|
||||
case SDLK_AC_STOP: return XF86XK_Stop;
|
||||
case SDLK_AC_REFRESH: return XF86XK_Refresh;
|
||||
case SDLK_AC_BOOKMARKS: return XF86XK_Book; // ?
|
||||
//case SDLK_SOFTLEFT: return ;
|
||||
//case SDLK_SOFTRIGHT: return ;
|
||||
//case SDLK_CALL: return ;
|
||||
//case SDLK_ENDCALL: return ;
|
||||
case SDLK_LEFT_TAB: return XK_ISO_Left_Tab;
|
||||
case SDLK_LEVEL5_SHIFT: return XK_ISO_Level5_Shift;
|
||||
case SDLK_MULTI_KEY_COMPOSE: return XK_Multi_key;
|
||||
case SDLK_LMETA: return XK_Meta_L;
|
||||
case SDLK_RMETA: return XK_Meta_R;
|
||||
case SDLK_LHYPER: return XK_Hyper_L;
|
||||
case SDLK_RHYPER: return XK_Hyper_R;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../Events.h"
|
||||
#include "../Keymap.h"
|
||||
#include "../Platform.h"
|
||||
|
||||
#include <BAN/Vector.h>
|
||||
@@ -25,6 +26,8 @@ struct BananCursor final : public PlatformCursor
|
||||
int32_t origin_y;
|
||||
};
|
||||
|
||||
static BAN::ErrorOr<void> bananos_initialize_keymap();
|
||||
|
||||
static bool bananos_initialize(uint32_t* display_w, uint32_t* display_h)
|
||||
{
|
||||
auto attributes = LibGUI::Window::default_attributes;
|
||||
@@ -40,6 +43,12 @@ static bool bananos_initialize(uint32_t* display_w, uint32_t* display_h)
|
||||
*display_w = dummy_or_error.value()->width();
|
||||
*display_h = dummy_or_error.value()->height();
|
||||
|
||||
if (auto ret = bananos_initialize_keymap(); ret.is_error())
|
||||
{
|
||||
dwarnln("Could not initialize keymap: {}", ret.error());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -103,7 +112,11 @@ static BAN::ErrorOr<BAN::UniqPtr<PlatformWindow>> bananos_create_window(Platform
|
||||
(event.shift() ? (1 << 0) : 0) |
|
||||
(event.caps_lock() ? (1 << 1) : 0) |
|
||||
(event.ctrl() ? (1 << 2) : 0) |
|
||||
(event.alt() ? (1 << 3) : 0);
|
||||
(event.alt() ? (1 << 3) : 0) |
|
||||
(event.num_lock() ? (1 << 4) : 0) |
|
||||
// level5 shift
|
||||
// super
|
||||
(event.ralt() ? (1 << 7) : 0); // FIXME: altgr
|
||||
on_key_event(wid, event.scancode, xmod, event.pressed());
|
||||
});
|
||||
|
||||
@@ -120,13 +133,6 @@ static void bananos_request_resize(PlatformWindow* window, uint32_t width, uint3
|
||||
banan_window.window->request_resize(width, height);
|
||||
}
|
||||
|
||||
static void bananos_request_reposition(PlatformWindow* window, int32_t x, int32_t y)
|
||||
{
|
||||
(void)window;
|
||||
(void)x;
|
||||
(void)y;
|
||||
}
|
||||
|
||||
static void bananos_invalidate(PlatformWindow* window, const uint32_t* pixels, uint32_t x, uint32_t y, uint32_t width, uint32_t height)
|
||||
{
|
||||
auto& banan_window = *static_cast<BananWindow*>(window);
|
||||
@@ -147,31 +153,6 @@ static void bananos_request_fullscreen(PlatformWindow* window, bool fullscreen)
|
||||
banan_window.window->set_fullscreen(fullscreen);
|
||||
}
|
||||
|
||||
static void bananos_warp_pointer(int32_t x, int32_t y, bool relative)
|
||||
{
|
||||
(void)x;
|
||||
(void)y;
|
||||
(void)relative;
|
||||
}
|
||||
|
||||
static void bananos_query_pointer(int32_t* x, int32_t* y)
|
||||
{
|
||||
(void)x;
|
||||
(void)y;
|
||||
}
|
||||
|
||||
static void bananos_set_pointer_grab(PlatformWindow* window, bool grabbed)
|
||||
{
|
||||
(void)window;
|
||||
(void)grabbed;
|
||||
}
|
||||
|
||||
static BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> bananos_create_system_cursor(SystemCursorType type)
|
||||
{
|
||||
(void)type;
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
static BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> bananos_create_bitmap_cursor(const uint32_t* pixels, uint32_t width, uint32_t height, int32_t origin_x, int32_t origin_y)
|
||||
{
|
||||
auto cursor = TRY(BAN::UniqPtr<BananCursor>::create());
|
||||
@@ -207,12 +188,158 @@ PlatformOps g_platform_ops = {
|
||||
.create_window = bananos_create_window,
|
||||
.invalidate = bananos_invalidate,
|
||||
.request_resize = bananos_request_resize,
|
||||
.request_reposition = bananos_request_reposition,
|
||||
.request_reposition = nullptr,
|
||||
.request_fullscreen = bananos_request_fullscreen,
|
||||
.warp_pointer = bananos_warp_pointer,
|
||||
.query_pointer = nullptr, /* bananos_query_pointer */
|
||||
.set_pointer_grab = bananos_set_pointer_grab,
|
||||
.create_system_cursor = bananos_create_system_cursor,
|
||||
.warp_pointer = nullptr,
|
||||
.query_pointer = nullptr,
|
||||
.set_pointer_grab = nullptr,
|
||||
.create_system_cursor = nullptr,
|
||||
.create_bitmap_cursor = bananos_create_bitmap_cursor,
|
||||
.set_cursor = bananos_set_cursor,
|
||||
};
|
||||
|
||||
#include <LibInput/KeyboardLayout.h>
|
||||
#include <LibInput/KeyEvent.h>
|
||||
|
||||
static uint32_t bananos_key_to_x_keysym(LibInput::Key, bool upper);
|
||||
|
||||
static BAN::ErrorOr<void> bananos_initialize_keymap()
|
||||
{
|
||||
// FIXME: get this from somewhere (gui command? enviroment? tmp file?)
|
||||
const auto keymap_path = "./us.keymap"_sv;
|
||||
|
||||
TRY(LibInput::KeyboardLayout::initialize());
|
||||
|
||||
auto& keyboard_layout = LibInput::KeyboardLayout::get();
|
||||
TRY(keyboard_layout.load_from_file(keymap_path));
|
||||
|
||||
const BAN::Span<const LibInput::Key> banan_keymaps[] {
|
||||
keyboard_layout.keymap_normal(),
|
||||
keyboard_layout.keymap_shift(),
|
||||
keyboard_layout.keymap_altgr(),
|
||||
keyboard_layout.keymap_altgr(), // add shift+altgr map?
|
||||
};
|
||||
|
||||
for (size_t scancode = 0; scancode < g_keymap_size; scancode++)
|
||||
for (size_t layer = 0; layer < g_keymap_layers; layer++)
|
||||
if (const auto banan_key = banan_keymaps[layer][scancode]; banan_key != LibInput::Key::None)
|
||||
g_keymap[scancode][layer] = bananos_key_to_x_keysym(banan_key, layer % 2);
|
||||
|
||||
using LibInput::keycode_normal;
|
||||
using LibInput::keycode_numpad;
|
||||
|
||||
g_modifier_map[0][0] = keycode_normal(3, 0) + g_keymap_min_keycode; // lshift
|
||||
g_modifier_map[0][1] = keycode_normal(3, 12) + g_keymap_min_keycode; // rshift
|
||||
|
||||
g_modifier_map[1][0] = keycode_normal(2, 0) + g_keymap_min_keycode; // caps lock
|
||||
|
||||
g_modifier_map[2][0] = keycode_normal(4, 0) + g_keymap_min_keycode; // lctrl
|
||||
g_modifier_map[2][1] = keycode_normal(4, 6) + g_keymap_min_keycode; // rctrl
|
||||
|
||||
g_modifier_map[3][0] = keycode_normal(4, 2) + g_keymap_min_keycode; // lalt
|
||||
g_modifier_map[3][1] = keycode_normal(4, 5) + g_keymap_min_keycode; // ralt
|
||||
|
||||
g_modifier_map[4][0] = keycode_numpad(0, 0) + g_keymap_min_keycode; // num lock
|
||||
|
||||
//g_modifier_map[5][0] = level5 shift;
|
||||
|
||||
g_modifier_map[6][0] = keycode_normal(4, 1) + g_keymap_min_keycode; // lsuper
|
||||
g_modifier_map[6][1] = keycode_normal(4, 4) + g_keymap_min_keycode; // rsuper
|
||||
|
||||
g_modifier_map[7][0] = keycode_normal(4, 5) + g_keymap_min_keycode; // FIXME: altgr
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
#include <BAN/UTF8.h>
|
||||
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/XF86keysym.h>
|
||||
|
||||
#include <wctype.h>
|
||||
|
||||
static uint32_t bananos_key_to_x_keysym(LibInput::Key key, bool upper)
|
||||
{
|
||||
using namespace LibInput;
|
||||
|
||||
if (const char* utf8 = key_to_utf8(key, upper ? KeyEvent::LShift : 0))
|
||||
{
|
||||
const uint32_t codepoint = BAN::UTF8::to_codepoint(utf8);
|
||||
if (codepoint != BAN::UTF8::invalid && iswprint(codepoint))
|
||||
{
|
||||
if ((codepoint >= 0x20 && codepoint <= 0x7E) || (codepoint >= 0xA0 && codepoint <= 0xFF))
|
||||
return codepoint;
|
||||
return 0x01000000 | codepoint;
|
||||
}
|
||||
}
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case Key::F1: return XK_F1;
|
||||
case Key::F2: return XK_F2;
|
||||
case Key::F3: return XK_F3;
|
||||
case Key::F4: return XK_F4;
|
||||
case Key::F5: return XK_F5;
|
||||
case Key::F6: return XK_F6;
|
||||
case Key::F7: return XK_F7;
|
||||
case Key::F8: return XK_F8;
|
||||
case Key::F9: return XK_F9;
|
||||
case Key::F10: return XK_F10;
|
||||
case Key::F11: return XK_F11;
|
||||
case Key::F12: return XK_F12;
|
||||
case Key::Insert: return XK_Insert;
|
||||
case Key::PrintScreen: return XK_Print;
|
||||
case Key::Delete: return XK_Delete;
|
||||
case Key::Home: return XK_Home;
|
||||
case Key::End: return XK_End;
|
||||
case Key::PageUp: return XK_Page_Up;
|
||||
case Key::PageDown: return XK_Page_Down;
|
||||
case Key::Enter: return XK_Return;
|
||||
case Key::Backspace: return XK_BackSpace;
|
||||
case Key::Escape: return XK_Escape;
|
||||
case Key::Tab: return XK_Tab;
|
||||
case Key::CapsLock: return XK_Caps_Lock;
|
||||
case Key::LeftShift: return XK_Shift_L;
|
||||
case Key::LeftCtrl: return XK_Control_L;
|
||||
case Key::Super: return XK_Super_L;
|
||||
case Key::LeftAlt: return XK_Alt_L;
|
||||
case Key::RightAlt: return XK_Alt_R;
|
||||
case Key::RightCtrl: return XK_Control_R;
|
||||
case Key::RightShift: return XK_Shift_R;
|
||||
case Key::ArrowUp: return XK_Up;
|
||||
case Key::ArrowDown: return XK_Down;
|
||||
case Key::ArrowLeft: return XK_Left;
|
||||
case Key::ArrowRight: return XK_Right;
|
||||
case Key::NumLock: return XK_Num_Lock;
|
||||
case Key::ScrollLock: return XK_Scroll_Lock;
|
||||
case Key::Numpad0: return XK_KP_0;
|
||||
case Key::Numpad1: return XK_KP_1;
|
||||
case Key::Numpad2: return XK_KP_2;
|
||||
case Key::Numpad3: return XK_KP_3;
|
||||
case Key::Numpad4: return XK_KP_4;
|
||||
case Key::Numpad5: return XK_KP_5;
|
||||
case Key::Numpad6: return XK_KP_6;
|
||||
case Key::Numpad7: return XK_KP_7;
|
||||
case Key::Numpad8: return XK_KP_8;
|
||||
case Key::Numpad9: return XK_KP_9;
|
||||
case Key::NumpadPlus: return XK_KP_Add;
|
||||
case Key::NumpadMinus: return XK_KP_Subtract;
|
||||
case Key::NumpadMultiply: return XK_KP_Multiply;
|
||||
case Key::NumpadDivide: return XK_KP_Divide;
|
||||
case Key::NumpadEnter: return XK_KP_Enter;
|
||||
case Key::NumpadDecimal: return XK_KP_Decimal;
|
||||
case Key::VolumeMute: return XF86XK_AudioMute;
|
||||
case Key::VolumeUp: return XF86XK_AudioRaiseVolume;
|
||||
case Key::VolumeDown: return XF86XK_AudioLowerVolume;
|
||||
case Key::Calculator: return XF86XK_Calculator;
|
||||
case Key::MediaPlayPause: return XF86XK_AudioPlay;
|
||||
case Key::MediaStop: return XF86XK_AudioStop;
|
||||
case Key::MediaPrevious: return XF86XK_AudioPrev;
|
||||
case Key::MediaNext: return XF86XK_AudioNext;
|
||||
default: break;
|
||||
}
|
||||
|
||||
static_assert(static_cast<size_t>(Key::Count) == 145, "update keymap");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "Base.h"
|
||||
#include "Definitions.h"
|
||||
#include "Keymap.h"
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include <locale.h>
|
||||
#include <signal.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -99,6 +99,8 @@ int g_server_grabber_fd = -1;
|
||||
|
||||
int main()
|
||||
{
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
for (int sig = 1; sig < NSIG; sig++)
|
||||
if (sig != SIGWINCH)
|
||||
signal(sig, exit);
|
||||
@@ -259,8 +261,6 @@ int main()
|
||||
APPEND_ATOM_CUSTOM(_NET_WM_WINDOW_TYPE_UTILITY);
|
||||
#undef APPEND_ATOM_CUSTOM
|
||||
|
||||
MUST(initialize_keymap());
|
||||
|
||||
uint32_t display_w, display_h;
|
||||
if (!g_platform_ops.initialize(&display_w, &display_h))
|
||||
return 1;
|
||||
|
||||
Reference in New Issue
Block a user