Fix keymaps, reported info and add custom cursors

This commit is contained in:
Oskari Alaranta 2026-02-11 17:32:15 +02:00
parent 28a68069fb
commit a74d99de45
7 changed files with 797 additions and 297 deletions

View File

@ -17,6 +17,10 @@ namespace LibInput
KeyEvent key_event_from_raw(RawKeyEvent); KeyEvent key_event_from_raw(RawKeyEvent);
BAN::ErrorOr<void> load_from_file(BAN::StringView path); BAN::ErrorOr<void> load_from_file(BAN::StringView path);
BAN::Span<const Key> keymap_normal() const { return m_keycode_to_key_normal.span(); }
BAN::Span<const Key> keymap_shift() const { return m_keycode_to_key_shift.span(); }
BAN::Span<const Key> keymap_altgr() const { return m_keycode_to_key_altgr.span(); }
private: private:
KeyboardLayout(); KeyboardLayout();

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@ set(SOURCES
Base.cpp Base.cpp
Extensions.cpp Extensions.cpp
ExtRANDR.cpp ExtRANDR.cpp
Keymap.cpp
) )
add_executable(xbanan ${SOURCES}) add_executable(xbanan ${SOURCES})

View File

@ -37,6 +37,7 @@ struct Object
enum class Type enum class Type
{ {
Visual, Visual,
Cursor,
Window, Window,
Pixmap, Pixmap,
GraphicsContext, GraphicsContext,
@ -44,6 +45,15 @@ struct Object
Type type; Type type;
struct Cursor
{
uint32_t width;
uint32_t height;
int32_t origin_x;
int32_t origin_y;
BAN::Vector<uint32_t> pixels;
};
struct Window struct Window
{ {
bool mapped { false }; bool mapped { false };
@ -54,6 +64,7 @@ struct Object
int32_t cursor_y { -1 }; int32_t cursor_y { -1 };
uint32_t event_mask { 0 }; uint32_t event_mask { 0 };
WINDOW parent; WINDOW parent;
CURSOR cursor;
CARD16 c_class; CARD16 c_class;
BAN::Vector<WINDOW> children; BAN::Vector<WINDOW> children;
BAN::Variant< BAN::Variant<
@ -96,7 +107,7 @@ struct Object
uint32_t background; uint32_t background;
}; };
BAN::Variant<Window, Pixmap, GraphicsContext> object; BAN::Variant<Cursor, Window, Pixmap, GraphicsContext> object;
}; };
struct Client struct Client
@ -128,7 +139,7 @@ struct EpollThingy
BAN::Variant<Client, LibGUI::Window*> value; BAN::Variant<Client, LibGUI::Window*> value;
}; };
extern const xPixmapFormat g_formats[5]; extern const xPixmapFormat g_formats[6];
extern const xWindowRoot g_root; extern const xWindowRoot g_root;
extern const xDepth g_depth; extern const xDepth g_depth;
extern const xVisualType g_visual; extern const xVisualType g_visual;

347
xbanan/Keymap.cpp Normal file
View File

@ -0,0 +1,347 @@
#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];
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 {};
}

13
xbanan/Keymap.h Normal file
View File

@ -0,0 +1,13 @@
#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_layers = 4;
extern uint32_t g_keymap[0x100][g_keymap_layers];

View File

@ -1,12 +1,12 @@
#include "Base.h" #include "Base.h"
#include "Definitions.h" #include "Definitions.h"
#include "Extensions.h" #include "Extensions.h"
#include "Keymap.h"
#include "Utils.h" #include "Utils.h"
#include <X11/X.h> #include <X11/X.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <time.h>
#include <signal.h> #include <signal.h>
#include <sys/epoll.h> #include <sys/epoll.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -19,20 +19,25 @@
#include <netinet/in.h> #include <netinet/in.h>
#endif #endif
const xPixmapFormat g_formats[] { const xPixmapFormat g_formats[6] {
{ {
.depth = 1, .depth = 1,
.bitsPerPixel = 32, .bitsPerPixel = 1,
.scanLinePad = 32, .scanLinePad = 32,
}, },
{ {
.depth = 4, .depth = 4,
.bitsPerPixel = 32, .bitsPerPixel = 4,
.scanLinePad = 32, .scanLinePad = 32,
}, },
{ {
.depth = 8, .depth = 8,
.bitsPerPixel = 32, .bitsPerPixel = 8,
.scanLinePad = 32,
},
{
.depth = 16,
.bitsPerPixel = 16,
.scanLinePad = 32, .scanLinePad = 32,
}, },
{ {
@ -56,7 +61,7 @@ const xVisualType g_visual {
.visualID = 1, .visualID = 1,
.c_class = TrueColor, .c_class = TrueColor,
.bitsPerRGB = 8, .bitsPerRGB = 8,
.colormapEntries = 0, .colormapEntries = 256,
.redMask = 0xFF0000, .redMask = 0xFF0000,
.greenMask = 0x00FF00, .greenMask = 0x00FF00,
.blueMask = 0x0000FF, .blueMask = 0x0000FF,
@ -72,8 +77,8 @@ const xWindowRoot g_root {
.pixHeight = 800, .pixHeight = 800,
.mmWidth = 1280, .mmWidth = 1280,
.mmHeight = 800, .mmHeight = 800,
.minInstalledMaps = 0, .minInstalledMaps = 1,
.maxInstalledMaps = 0, .maxInstalledMaps = 1,
.rootVisualID = g_visual.visualID, .rootVisualID = g_visual.visualID,
.backingStore = 0, .backingStore = 0,
.saveUnders = 0, .saveUnders = 0,
@ -124,13 +129,13 @@ int main()
if (sig != SIGWINCH) if (sig != SIGWINCH)
signal(sig, exit); signal(sig, exit);
#if USE_UNIX_SOCKET
if (mkdir("/tmp/.X11-unix", 01777) == -1 && errno != EEXIST) if (mkdir("/tmp/.X11-unix", 01777) == -1 && errno != EEXIST)
{ {
perror("xbanan: mkdir"); perror("xbanan: mkdir");
return 1; return 1;
} }
#if USE_UNIX_SOCKET
int server_sock = socket(AF_UNIX, SOCK_STREAM, 0); int server_sock = socket(AF_UNIX, SOCK_STREAM, 0);
#else #else
int server_sock = socket(AF_INET, SOCK_STREAM, 0); int server_sock = socket(AF_INET, SOCK_STREAM, 0);
@ -262,6 +267,8 @@ int main()
APPEND_ATOM(XA_WM_TRANSIENT_FOR); APPEND_ATOM(XA_WM_TRANSIENT_FOR);
#undef APPEND_ATOM #undef APPEND_ATOM
MUST(initialize_keymap());
install_extension("BIG-REQUESTS"_sv, extension_bigrequests); install_extension("BIG-REQUESTS"_sv, extension_bigrequests);
printf("xbanan started\n"); printf("xbanan started\n");