@ -7,21 +7,15 @@
# include "../util.h"
# define LAYOUT_MAX 256
/* Given a token (sym) from the xkb_symbols string
* check whether it is a valid layout / variant . The
* EXCLUDES array contains invalid layouts / variants
* that are part of the xkb rules config .
*/
static int
IsLayoutOrV ariant( char * sym )
valid_layout_or_variant ( char * sym )
{
static const char * EXCLUDES [ ] = { " evdev " , " inet " , " pc " , " base " } ;
size_t i ;
for ( i = 0 ; i < sizeof ( EXCLUDES ) / sizeof ( EXCLUDES [ 0 ] ) ; + + i ) {
if ( strstr ( sym , EXCLUDES [ i ] ) ) {
/* invalid symbols from xkb rules config */
static const char * invalid [ ] = { " evdev " , " inet " , " pc " , " base " } ;
for ( i = 0 ; i < LEN ( invalid ) ; i + + ) {
if ( ! strncmp ( sym , invalid [ i ] , strlen ( invalid [ i ] ) ) ) {
return 0 ;
}
}
@ -29,70 +23,65 @@ IsLayoutOrVariant(char *sym)
return 1 ;
}
static void
GetKeyL ayout( char * syms , char layout [ ] , int groupN um)
static char *
get_l ayout( char * syms , int grp_n um)
{
char * token , * copy , * delims ;
int group ;
delims = " +: " ;
group = 0 ;
copy = strdup ( syms ) ;
token = strtok ( copy , delims ) ;
while ( token ! = NULL & & group < = groupNum ) {
/* Ignore :2,:3,:4 which represent additional layout
* groups
*/
if ( IsLayoutOrVariant ( token )
& & ! ( strlen ( token ) = = 1 & & isdigit ( token [ 0 ] ) ) ) {
strncpy ( layout , token , LAYOUT_MAX ) ;
group + + ;
char * tok , * layout ;
int grp ;
layout = NULL ;
tok = strtok ( syms , " +: " ) ;
for ( grp = 0 ; tok & & grp < = grp_num ; tok = strtok ( NULL , " +: " ) ) {
if ( ! valid_layout_or_variant ( tok ) ) {
continue ;
} else if ( strlen ( tok ) = = 1 & & isdigit ( tok [ 0 ] ) ) {
/* ignore :2, :3, :4 (additional layout groups) */
continue ;
}
token = strtok ( NULL , delims ) ;
layout = tok ;
grp + + ;
}
free ( copy ) ;
return layout ;
}
const char *
keymap ( void )
{
static char layout [ LAYOUT_MAX ] ;
Display * dpy ;
char * symbols = NULL ;
XkbDescRec * desc = NULL ;
XkbDescRec * desc ;
XkbStateRec state ;
char * symbols , * layout ;
memset ( layout , ' \0 ' , LAYOUT_MAX ) ;
layout = NULL ;
if ( ! ( dpy = XOpenDisplay ( NULL ) ) ) {
warn ( " XOpenDisplay: Failed to open display " ) ;
return NULL ;
}
;
if ( ! ( desc = XkbAllocKeyboard ( ) ) ) {
warn ( " XkbAllocKeyboard: failed to allocate keyboard " ) ;
XCloseDisplay ( dpy ) ;
return NULL ;
warn ( " XkbAllocKeyboard: Failed to allocate keyboard " ) ;
goto end ;
}
XkbGetNames ( dpy , XkbSymbolsNameMask , desc ) ;
if ( desc - > names ) {
XkbStateRec state ;
XkbGetState ( dpy , XkbUseCoreKbd , & state ) ;
symbols = XGetAtomName ( dpy , desc - > names - > symbols ) ;
GetKeyLayout ( symbols , layout , state . group ) ;
XFree ( symbols ) ;
} else {
warn ( " XkbGetNames: failed to retrieve symbols for keys " ) ;
return NULL ;
if ( XkbGetNames ( dpy , XkbSymbolsNameMask , desc ) ) {
warn ( " XkbGetNames: Failed to retrieve key symbols " ) ;
goto end ;
}
if ( XkbGetState ( dpy , XkbUseCoreKbd , & state ) ) {
warn ( " XkbGetState: Failed to retrieve keyboard state " ) ;
goto end ;
}
if ( ! ( symbols = XGetAtomName ( dpy , desc - > names - > symbols ) ) ) {
warn ( " XGetAtomName: Failed to get atom name " ) ;
goto end ;
}
layout = ( char * ) bprintf ( " %s " , get_layout ( symbols , state . group ) ) ;
XFree ( symbols ) ;
end :
XkbFreeKeyboard ( desc , XkbSymbolsNameMask , 1 ) ;
XCloseDisplay ( dpy ) ;
if ( XCloseDisplay ( dpy ) ) {
warn ( " XCloseDisplay: Failed to close display " ) ;
}
return layout ;
}