Remove banan-os's LibInput dependency

Platforms now define their own keymaps
This commit is contained in:
2026-06-03 19:06:58 +03:00
parent aa70815f5f
commit d0606a1939
9 changed files with 488 additions and 565 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 {};
}

View File

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

View File

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

View File

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

View File

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