2024-05-03 22:34:10 +01:00
# include "IKeyboard.hpp"
# include "../defines.hpp"
2024-06-11 17:17:45 +02:00
# include "../helpers/varlist/VarList.hpp"
2024-05-03 22:34:10 +01:00
# include "../managers/input/InputManager.hpp"
2024-07-21 13:09:54 +02:00
# include "../managers/SeatManager.hpp"
# include "../config/ConfigManager.hpp"
# include <sys/mman.h>
# include <aquamarine/input/Input.hpp>
# include <cstring>
2024-05-03 22:34:10 +01:00
2025-01-30 12:30:12 +01:00
using namespace Hyprutils : : OS ;
2024-07-21 13:09:54 +02:00
# define LED_COUNT 3
constexpr static std : : array < const char * , 8 > MODNAMES = {
XKB_MOD_NAME_SHIFT , XKB_MOD_NAME_CAPS , XKB_MOD_NAME_CTRL , XKB_MOD_NAME_ALT , XKB_MOD_NAME_NUM , " Mod3 " , XKB_MOD_NAME_LOGO , " Mod5 " ,
} ;
constexpr static std : : array < const char * , 3 > LEDNAMES = { XKB_LED_NAME_NUM , XKB_LED_NAME_CAPS , XKB_LED_NAME_SCROLL } ;
//
2024-05-03 22:34:10 +01:00
uint32_t IKeyboard : : getCapabilities ( ) {
return HID_INPUT_CAPABILITY_KEYBOARD ;
}
2024-05-05 22:18:10 +01:00
eHIDType IKeyboard : : getType ( ) {
return HID_TYPE_KEYBOARD ;
}
2024-05-03 22:34:10 +01:00
IKeyboard : : ~ IKeyboard ( ) {
2025-04-29 19:51:07 +02:00
m_events . destroy . emit ( ) ;
2024-05-03 22:34:10 +01:00
2024-07-21 13:09:54 +02:00
clearManuallyAllocd ( ) ;
}
void IKeyboard : : clearManuallyAllocd ( ) {
2025-04-29 19:51:07 +02:00
if ( m_xkbStaticState )
xkb_state_unref ( m_xkbStaticState ) ;
2024-07-21 13:09:54 +02:00
2025-04-29 19:51:07 +02:00
if ( m_xkbState )
xkb_state_unref ( m_xkbState ) ;
2024-07-21 13:09:54 +02:00
2025-04-29 19:51:07 +02:00
if ( m_xkbKeymap )
xkb_keymap_unref ( m_xkbKeymap ) ;
2024-07-21 13:09:54 +02:00
2025-04-29 19:51:07 +02:00
if ( m_xkbSymState )
xkb_state_unref ( m_xkbSymState ) ;
2025-01-28 10:15:08 +01:00
2025-04-29 19:51:07 +02:00
m_xkbSymState = nullptr ;
m_xkbKeymap = nullptr ;
m_xkbState = nullptr ;
m_xkbStaticState = nullptr ;
m_xkbKeymapFD . reset ( ) ;
2025-09-11 20:42:20 +03:00
m_xkbKeymapV1FD . reset ( ) ;
2024-07-21 13:09:54 +02:00
}
void IKeyboard : : setKeymap ( const SStringRuleNames & rules ) {
2025-04-29 19:51:07 +02:00
if ( m_keymapOverridden ) {
2024-07-25 13:02:05 +02:00
Debug : : log ( LOG , " Ignoring setKeymap: keymap is overridden " ) ;
return ;
}
2025-04-29 19:51:07 +02:00
m_currentRules = rules ;
2024-07-21 13:09:54 +02:00
xkb_rule_names XKBRULES = {
. rules = rules . rules . c_str ( ) ,
. model = rules . model . c_str ( ) ,
. layout = rules . layout . c_str ( ) ,
. variant = rules . variant . c_str ( ) ,
. options = rules . options . c_str ( ) ,
} ;
const auto CONTEXT = xkb_context_new ( XKB_CONTEXT_NO_FLAGS ) ;
if ( ! CONTEXT ) {
Debug : : log ( ERR , " setKeymap: CONTEXT null?? " ) ;
2024-05-03 22:34:10 +01:00
return ;
2024-07-21 13:09:54 +02:00
}
clearManuallyAllocd ( ) ;
Debug : : log ( LOG , " Attempting to create a keymap for layout {} with variant {} (rules: {}, model: {}, options: {}) " , rules . layout , rules . variant , rules . rules , rules . model ,
rules . options ) ;
2025-04-29 19:51:07 +02:00
if ( ! m_xkbFilePath . empty ( ) ) {
auto path = absolutePath ( m_xkbFilePath , g_pConfigManager - > m_configCurrentPath ) ;
2024-07-21 13:09:54 +02:00
if ( FILE * const KEYMAPFILE = fopen ( path . c_str ( ) , " r " ) ; ! KEYMAPFILE )
Debug : : log ( ERR , " Cannot open input:kb_file= file for reading " ) ;
else {
2025-09-11 20:42:20 +03:00
m_xkbKeymap = xkb_keymap_new_from_file ( CONTEXT , KEYMAPFILE , XKB_KEYMAP_FORMAT_TEXT_V2 , XKB_KEYMAP_COMPILE_NO_FLAGS ) ;
2024-07-21 13:09:54 +02:00
fclose ( KEYMAPFILE ) ;
}
}
2025-04-29 19:51:07 +02:00
if ( ! m_xkbKeymap )
2025-09-11 20:42:20 +03:00
m_xkbKeymap = xkb_keymap_new_from_names2 ( CONTEXT , & XKBRULES , XKB_KEYMAP_FORMAT_TEXT_V2 , XKB_KEYMAP_COMPILE_NO_FLAGS ) ;
2024-07-21 13:09:54 +02:00
2025-04-29 19:51:07 +02:00
if ( ! m_xkbKeymap ) {
2024-07-21 13:09:54 +02:00
g_pConfigManager - > addParseError ( " Invalid keyboard layout passed. ( rules: " + rules . rules + " , model: " + rules . model + " , variant: " + rules . variant +
" , options: " + rules . options + " , layout: " + rules . layout + " ) " ) ;
Debug : : log ( ERR , " Keyboard layout {} with variant {} (rules: {}, model: {}, options: {}) couldn't have been loaded. " , rules . layout , rules . variant , rules . rules , rules . model ,
rules . options ) ;
memset ( & XKBRULES , 0 , sizeof ( XKBRULES ) ) ;
2025-04-29 19:51:07 +02:00
m_currentRules . rules = " " ;
m_currentRules . model = " " ;
m_currentRules . variant = " " ;
m_currentRules . options = " " ;
m_currentRules . layout = " us " ;
2024-07-21 13:09:54 +02:00
2025-09-11 20:42:20 +03:00
m_xkbKeymap = xkb_keymap_new_from_names2 ( CONTEXT , & XKBRULES , XKB_KEYMAP_FORMAT_TEXT_V2 , XKB_KEYMAP_COMPILE_NO_FLAGS ) ;
}
2025-04-29 19:51:07 +02:00
updateXKBTranslationState ( m_xkbKeymap ) ;
2024-07-21 13:09:54 +02:00
2025-04-29 19:51:07 +02:00
const auto NUMLOCKON = g_pConfigManager - > getDeviceInt ( m_hlName , " numlock_by_default " , " input:numlock_by_default " ) ;
2024-07-21 13:09:54 +02:00
if ( NUMLOCKON = = 1 ) {
// lock numlock
2025-04-29 19:51:07 +02:00
const auto IDX = xkb_map_mod_get_index ( m_xkbKeymap , XKB_MOD_NAME_NUM ) ;
2024-07-21 13:09:54 +02:00
if ( IDX ! = XKB_MOD_INVALID )
2025-08-14 19:44:56 +05:00
m_modifiersState . locked | = sc < uint32_t > ( 1 ) < < IDX ;
2024-07-21 13:09:54 +02:00
2024-08-23 22:35:52 +03:00
// 0 to avoid mods getting stuck if depressed during reload
2025-04-29 19:51:07 +02:00
updateModifiers ( 0 , 0 , m_modifiersState . locked , m_modifiersState . group ) ;
2024-07-21 13:09:54 +02:00
}
2025-04-29 19:51:07 +02:00
for ( size_t i = 0 ; i < std : : min ( LEDNAMES . size ( ) , m_ledIndexes . size ( ) ) ; + + i ) {
m_ledIndexes [ i ] = xkb_map_led_get_index ( m_xkbKeymap , LEDNAMES [ i ] ) ;
Debug : : log ( LOG , " xkb: LED index {} (name {}) got index {} " , i , LEDNAMES [ i ] , m_ledIndexes [ i ] ) ;
2024-07-21 13:09:54 +02:00
}
2025-04-29 19:51:07 +02:00
for ( size_t i = 0 ; i < std : : min ( MODNAMES . size ( ) , m_modIndexes . size ( ) ) ; + + i ) {
m_modIndexes [ i ] = xkb_map_mod_get_index ( m_xkbKeymap , MODNAMES [ i ] ) ;
Debug : : log ( LOG , " xkb: Mod index {} (name {}) got index {} " , i , MODNAMES [ i ] , m_modIndexes [ i ] ) ;
2024-07-21 13:09:54 +02:00
}
2024-05-03 22:34:10 +01:00
2024-07-25 13:02:05 +02:00
updateKeymapFD ( ) ;
xkb_context_unref ( CONTEXT ) ;
g_pSeatManager - > updateActiveKeyboardData ( ) ;
}
void IKeyboard : : updateKeymapFD ( ) {
2025-04-29 19:51:07 +02:00
Debug : : log ( LOG , " Updating keymap fd for keyboard {} " , m_deviceName ) ;
2024-07-25 13:02:05 +02:00
2025-04-29 19:51:07 +02:00
if ( m_xkbKeymapFD . isValid ( ) )
m_xkbKeymapFD . reset ( ) ;
2024-07-25 13:02:05 +02:00
2025-09-11 20:42:20 +03:00
if ( m_xkbKeymapV1FD . isValid ( ) )
m_xkbKeymapV1FD . reset ( ) ;
auto cKeymapStr = xkb_keymap_get_as_string ( m_xkbKeymap , XKB_KEYMAP_FORMAT_TEXT_V2 ) ;
2025-04-29 19:51:07 +02:00
m_xkbKeymapString = cKeymapStr ;
2025-09-29 15:10:15 +03:00
free ( cKeymapStr ) ; // NOLINT(cppcoreguidelines-no-malloc,-warnings-as-errors)
2025-09-19 17:58:03 +03:00
auto cKeymapV1Str = xkb_keymap_get_as_string ( m_xkbKeymap , XKB_KEYMAP_FORMAT_TEXT_V1 ) ;
2025-09-11 20:42:20 +03:00
m_xkbKeymapV1String = cKeymapV1Str ;
2025-09-29 15:10:15 +03:00
free ( cKeymapV1Str ) ; // NOLINT(cppcoreguidelines-no-malloc,-warnings-as-errors)
2024-07-21 13:09:54 +02:00
2025-09-11 20:42:20 +03:00
CFileDescriptor rw , ro , rwV1 , roV1 ;
2025-04-29 19:51:07 +02:00
if ( ! allocateSHMFilePair ( m_xkbKeymapString . length ( ) + 1 , rw , ro ) )
2024-07-21 13:09:54 +02:00
Debug : : log ( ERR , " IKeyboard: failed to allocate shm pair for the keymap " ) ;
2025-09-11 20:42:20 +03:00
else if ( ! allocateSHMFilePair ( m_xkbKeymapV1String . length ( ) + 1 , rwV1 , roV1 ) ) {
ro . reset ( ) ;
rw . reset ( ) ;
Debug : : log ( ERR , " IKeyboard: failed to allocate shm pair for keymap V1 " ) ;
} else {
auto keymapFDDest = mmap ( nullptr , m_xkbKeymapString . length ( ) + 1 , PROT_READ | PROT_WRITE , MAP_SHARED , rw . get ( ) , 0 ) ;
auto keymapV1FDDest = mmap ( nullptr , m_xkbKeymapV1String . length ( ) + 1 , PROT_READ | PROT_WRITE , MAP_SHARED , rwV1 . get ( ) , 0 ) ;
2025-01-30 12:30:12 +01:00
rw . reset ( ) ;
2025-09-11 20:42:20 +03:00
rwV1 . reset ( ) ;
if ( keymapFDDest = = MAP_FAILED | | keymapV1FDDest = = MAP_FAILED ) {
2024-07-21 13:09:54 +02:00
Debug : : log ( ERR , " IKeyboard: failed to mmap a shm pair for the keymap " ) ;
2025-01-30 12:30:12 +01:00
ro . reset ( ) ;
2025-09-11 20:42:20 +03:00
roV1 . reset ( ) ;
2024-07-21 13:09:54 +02:00
} else {
2025-04-29 19:51:07 +02:00
memcpy ( keymapFDDest , m_xkbKeymapString . c_str ( ) , m_xkbKeymapString . length ( ) ) ;
munmap ( keymapFDDest , m_xkbKeymapString . length ( ) + 1 ) ;
m_xkbKeymapFD = std : : move ( ro ) ;
2025-09-11 20:42:20 +03:00
memcpy ( keymapV1FDDest , m_xkbKeymapV1String . c_str ( ) , m_xkbKeymapV1String . length ( ) ) ;
munmap ( keymapV1FDDest , m_xkbKeymapV1String . length ( ) + 1 ) ;
m_xkbKeymapV1FD = std : : move ( roV1 ) ;
2024-07-21 13:09:54 +02:00
}
}
2025-09-11 20:42:20 +03:00
Debug : : log ( LOG , " Updated keymap fd to {}, keymap V1 to: {} " , m_xkbKeymapFD . get ( ) , m_xkbKeymapV1FD . get ( ) ) ;
2024-05-03 22:34:10 +01:00
}
void IKeyboard : : updateXKBTranslationState ( xkb_keymap * const keymap ) {
2025-04-29 19:51:07 +02:00
if ( m_xkbStaticState )
xkb_state_unref ( m_xkbStaticState ) ;
2024-07-25 13:02:05 +02:00
2025-04-29 19:51:07 +02:00
if ( m_xkbState )
xkb_state_unref ( m_xkbState ) ;
2024-07-21 13:09:54 +02:00
2025-04-29 19:51:07 +02:00
if ( m_xkbSymState )
xkb_state_unref ( m_xkbSymState ) ;
2024-10-08 13:15:53 +01:00
2025-04-29 19:51:07 +02:00
m_xkbState = nullptr ;
m_xkbStaticState = nullptr ;
m_xkbSymState = nullptr ;
2024-05-03 22:34:10 +01:00
if ( keymap ) {
2025-08-14 19:44:56 +05:00
Debug : : log ( LOG , " Updating keyboard {:x}'s translation state from a provided keymap " , rc < uintptr_t > ( this ) ) ;
2025-04-29 19:51:07 +02:00
m_xkbStaticState = xkb_state_new ( keymap ) ;
m_xkbState = xkb_state_new ( keymap ) ;
m_xkbSymState = xkb_state_new ( keymap ) ;
2024-05-03 22:34:10 +01:00
return ;
}
2025-04-29 19:51:07 +02:00
const auto KEYMAP = m_xkbKeymap ;
const auto STATE = m_xkbState ;
2024-05-03 22:34:10 +01:00
const auto LAYOUTSNUM = xkb_keymap_num_layouts ( KEYMAP ) ;
const auto PCONTEXT = xkb_context_new ( XKB_CONTEXT_NO_FLAGS ) ;
for ( uint32_t i = 0 ; i < LAYOUTSNUM ; + + i ) {
2024-05-07 10:07:50 -05:00
if ( xkb_state_layout_index_is_active ( STATE , i , XKB_STATE_LAYOUT_EFFECTIVE ) = = 1 ) {
2025-08-14 19:44:56 +05:00
Debug : : log ( LOG , " Updating keyboard {:x}'s translation state from an active index {} " , rc < uintptr_t > ( this ) , i ) ;
2024-05-03 22:34:10 +01:00
2025-04-29 19:51:07 +02:00
CVarList keyboardLayouts ( m_currentRules . layout , 0 , ' , ' ) ;
CVarList keyboardModels ( m_currentRules . model , 0 , ' , ' ) ;
CVarList keyboardVariants ( m_currentRules . variant , 0 , ' , ' ) ;
2024-05-03 22:34:10 +01:00
xkb_rule_names rules = { . rules = " " , . model = " " , . layout = " " , . variant = " " , . options = " " } ;
std : : string layout , model , variant ;
layout = keyboardLayouts [ i % keyboardLayouts . size ( ) ] ;
model = keyboardModels [ i % keyboardModels . size ( ) ] ;
variant = keyboardVariants [ i % keyboardVariants . size ( ) ] ;
rules . layout = layout . c_str ( ) ;
rules . model = model . c_str ( ) ;
rules . variant = variant . c_str ( ) ;
2025-09-11 20:42:20 +03:00
auto KEYMAP = xkb_keymap_new_from_names2 ( PCONTEXT , & rules , XKB_KEYMAP_FORMAT_TEXT_V2 , XKB_KEYMAP_COMPILE_NO_FLAGS ) ;
2024-05-03 22:34:10 +01:00
if ( ! KEYMAP ) {
Debug : : log ( ERR , " updateXKBTranslationState: keymap failed 1, fallback without model/variant " ) ;
rules . model = " " ;
rules . variant = " " ;
2025-09-11 20:42:20 +03:00
KEYMAP = xkb_keymap_new_from_names2 ( PCONTEXT , & rules , XKB_KEYMAP_FORMAT_TEXT_V2 , XKB_KEYMAP_COMPILE_NO_FLAGS ) ;
2024-05-03 22:34:10 +01:00
}
if ( ! KEYMAP ) {
Debug : : log ( ERR , " updateXKBTranslationState: keymap failed 2, fallback to us " ) ;
rules . layout = " us " ;
2025-09-11 20:42:20 +03:00
KEYMAP = xkb_keymap_new_from_names2 ( PCONTEXT , & rules , XKB_KEYMAP_FORMAT_TEXT_V2 , XKB_KEYMAP_COMPILE_NO_FLAGS ) ;
2024-05-03 22:34:10 +01:00
}
2025-04-29 19:51:07 +02:00
m_xkbState = xkb_state_new ( KEYMAP ) ;
m_xkbStaticState = xkb_state_new ( KEYMAP ) ;
m_xkbSymState = xkb_state_new ( KEYMAP ) ;
2024-05-03 22:34:10 +01:00
xkb_keymap_unref ( KEYMAP ) ;
xkb_context_unref ( PCONTEXT ) ;
return ;
}
}
2025-08-14 19:44:56 +05:00
Debug : : log ( LOG , " Updating keyboard {:x}'s translation state from an unknown index " , rc < uintptr_t > ( this ) ) ;
2024-05-03 22:34:10 +01:00
xkb_rule_names rules = {
2025-04-29 19:51:07 +02:00
. rules = m_currentRules . rules . c_str ( ) ,
. model = m_currentRules . model . c_str ( ) ,
. layout = m_currentRules . layout . c_str ( ) ,
. variant = m_currentRules . variant . c_str ( ) ,
. options = m_currentRules . options . c_str ( ) ,
2024-05-03 22:34:10 +01:00
} ;
2025-09-11 20:42:20 +03:00
const auto NEWKEYMAP = xkb_keymap_new_from_names2 ( PCONTEXT , & rules , XKB_KEYMAP_FORMAT_TEXT_V2 , XKB_KEYMAP_COMPILE_NO_FLAGS ) ;
2024-05-03 22:34:10 +01:00
2025-04-29 19:51:07 +02:00
m_xkbState = xkb_state_new ( NEWKEYMAP ) ;
m_xkbStaticState = xkb_state_new ( NEWKEYMAP ) ;
m_xkbSymState = xkb_state_new ( NEWKEYMAP ) ;
2024-05-03 22:34:10 +01:00
xkb_keymap_unref ( NEWKEYMAP ) ;
xkb_context_unref ( PCONTEXT ) ;
}
2025-09-09 15:19:51 +02:00
std : : optional < xkb_layout_index_t > IKeyboard : : getActiveLayoutIndex ( ) {
const auto KEYMAP = m_xkbKeymap ;
const auto STATE = m_xkbState ;
const auto LAYOUTSNUM = xkb_keymap_num_layouts ( KEYMAP ) ;
for ( xkb_layout_index_t i = 0 ; i < LAYOUTSNUM ; + + i ) {
if ( xkb_state_layout_index_is_active ( STATE , i , XKB_STATE_LAYOUT_EFFECTIVE ) = = 1 )
return i ;
}
return { } ;
}
2024-05-03 22:34:10 +01:00
std : : string IKeyboard : : getActiveLayout ( ) {
2025-04-29 19:51:07 +02:00
const auto KEYMAP = m_xkbKeymap ;
const auto STATE = m_xkbState ;
2024-05-03 22:34:10 +01:00
const auto LAYOUTSNUM = xkb_keymap_num_layouts ( KEYMAP ) ;
for ( uint32_t i = 0 ; i < LAYOUTSNUM ; + + i ) {
2024-05-07 10:07:50 -05:00
if ( xkb_state_layout_index_is_active ( STATE , i , XKB_STATE_LAYOUT_EFFECTIVE ) = = 1 ) {
2024-05-03 22:34:10 +01:00
const auto LAYOUTNAME = xkb_keymap_layout_get_name ( KEYMAP , i ) ;
if ( LAYOUTNAME )
return std : : string ( LAYOUTNAME ) ;
return " error " ;
}
}
return " none " ;
}
2024-07-28 19:46:38 +09:00
std : : optional < uint32_t > IKeyboard : : getLEDs ( ) {
2025-04-29 19:51:07 +02:00
if ( m_xkbState = = nullptr )
2024-07-28 19:46:38 +09:00
return { } ;
2024-05-03 22:34:10 +01:00
uint32_t leds = 0 ;
2025-08-14 19:44:56 +05:00
for ( uint32_t i = 0 ; i < std : : min ( sc < size_t > ( LED_COUNT ) , m_ledIndexes . size ( ) ) ; + + i ) {
2025-04-29 19:51:07 +02:00
if ( xkb_state_led_index_is_active ( m_xkbState , m_ledIndexes [ i ] ) )
2024-05-03 22:34:10 +01:00
leds | = ( 1 < < i ) ;
}
2024-07-28 19:46:38 +09:00
return leds ;
}
void IKeyboard : : updateLEDs ( ) {
std : : optional < uint32_t > leds = getLEDs ( ) ;
if ( ! leds . has_value ( ) )
return ;
updateLEDs ( leds . value ( ) ) ;
2024-05-15 00:14:43 +09:00
}
void IKeyboard : : updateLEDs ( uint32_t leds ) {
2025-04-29 19:51:07 +02:00
if ( ! m_xkbState )
2024-05-15 00:14:43 +09:00
return ;
2025-04-29 19:51:07 +02:00
if ( isVirtual ( ) & & g_pInputManager - > shouldIgnoreVirtualKeyboard ( m_self . lock ( ) ) )
2024-05-03 22:34:10 +01:00
return ;
2024-07-21 13:09:54 +02:00
if ( ! aq ( ) )
return ;
aq ( ) - > updateLEDs ( leds ) ;
}
uint32_t IKeyboard : : getModifiers ( ) {
2025-04-29 19:51:07 +02:00
uint32_t modMask = m_modifiersState . depressed | m_modifiersState . latched ;
2024-07-21 13:09:54 +02:00
uint32_t mods = 0 ;
2025-04-29 19:51:07 +02:00
for ( size_t i = 0 ; i < m_modIndexes . size ( ) ; + + i ) {
if ( m_modIndexes [ i ] = = XKB_MOD_INVALID )
2024-07-21 13:09:54 +02:00
continue ;
2025-04-29 19:51:07 +02:00
if ( ! ( modMask & ( 1 < < m_modIndexes [ i ] ) ) )
2024-07-21 13:09:54 +02:00
continue ;
mods | = ( 1 < < i ) ;
}
return mods ;
}
void IKeyboard : : updateModifiers ( uint32_t depressed , uint32_t latched , uint32_t locked , uint32_t group ) {
2025-04-29 19:51:07 +02:00
if ( ! m_xkbState )
2024-07-21 13:09:54 +02:00
return ;
2025-04-29 19:51:07 +02:00
xkb_state_update_mask ( m_xkbState , depressed , latched , locked , 0 , 0 , group ) ;
2024-07-21 13:09:54 +02:00
2025-04-29 19:51:07 +02:00
if ( m_xkbSymState )
xkb_state_update_mask ( m_xkbSymState , 0 , 0 , 0 , 0 , 0 , group ) ;
2024-10-08 13:15:53 +01:00
2024-07-21 13:09:54 +02:00
if ( ! updateModifiersState ( ) )
return ;
2025-04-29 19:51:07 +02:00
m_keyboardEvents . modifiers . emit ( SModifiersEvent {
. depressed = m_modifiersState . depressed ,
. latched = m_modifiersState . latched ,
. locked = m_modifiersState . locked ,
. group = m_modifiersState . group ,
2024-07-27 18:43:45 +03:00
} ) ;
2024-07-21 13:09:54 +02:00
updateLEDs ( ) ;
}
bool IKeyboard : : updateModifiersState ( ) {
2025-04-29 19:51:07 +02:00
if ( ! m_xkbState )
2024-07-21 13:09:54 +02:00
return false ;
2025-04-29 19:51:07 +02:00
auto depressed = xkb_state_serialize_mods ( m_xkbState , XKB_STATE_MODS_DEPRESSED ) ;
auto latched = xkb_state_serialize_mods ( m_xkbState , XKB_STATE_MODS_LATCHED ) ;
auto locked = xkb_state_serialize_mods ( m_xkbState , XKB_STATE_MODS_LOCKED ) ;
auto group = xkb_state_serialize_layout ( m_xkbState , XKB_STATE_LAYOUT_EFFECTIVE ) ;
2024-07-21 13:09:54 +02:00
2025-04-29 19:51:07 +02:00
if ( depressed = = m_modifiersState . depressed & & latched = = m_modifiersState . latched & & locked = = m_modifiersState . locked & & group = = m_modifiersState . group )
2024-07-21 13:09:54 +02:00
return false ;
2025-04-29 19:51:07 +02:00
m_modifiersState . depressed = depressed ;
m_modifiersState . latched = latched ;
m_modifiersState . locked = locked ;
m_modifiersState . group = group ;
2024-07-21 13:09:54 +02:00
return true ;
}
void IKeyboard : : updateXkbStateWithKey ( uint32_t xkbKey , bool pressed ) {
2025-04-29 19:51:07 +02:00
xkb_state_update_key ( m_xkbState , xkbKey , pressed ? XKB_KEY_DOWN : XKB_KEY_UP ) ;
2024-07-21 13:09:54 +02:00
if ( updateModifiersState ( ) ) {
2025-04-29 19:51:07 +02:00
if ( m_xkbSymState )
xkb_state_update_mask ( m_xkbSymState , 0 , 0 , 0 , 0 , 0 , m_modifiersState . group ) ;
m_keyboardEvents . modifiers . emit ( SModifiersEvent {
. depressed = m_modifiersState . depressed ,
. latched = m_modifiersState . latched ,
. locked = m_modifiersState . locked ,
. group = m_modifiersState . group ,
2024-07-21 13:09:54 +02:00
} ) ;
}
2024-05-03 22:34:10 +01:00
}
2025-08-04 16:29:39 -03:00
bool IKeyboard : : updatePressed ( uint32_t key , bool pressed ) {
const auto contains = getPressed ( key ) ;
if ( contains & & pressed )
return false ;
if ( ! contains & & ! pressed )
return false ;
if ( contains )
std : : erase ( m_pressed , key ) ;
else
m_pressed . emplace_back ( key ) ;
return true ;
}
bool IKeyboard : : getPressed ( uint32_t key ) {
return std : : ranges : : contains ( m_pressed , key ) ;
}
bool IKeyboard : : shareStates ( ) {
return m_shareStates ;
}
2025-09-20 12:57:39 -03:00
void IKeyboard : : setShareStatesAuto ( bool shareStates ) {
if ( m_shareStatesAuto )
m_shareStates = shareStates ;
}