@ -3,6 +3,7 @@
# include <limits.h>
# include <float.h>
# include "sway/config.h"
# include "sway/input/keyboard.h"
# include "log.h"
struct input_config * new_input_config ( const char * identifier ) {
@ -133,22 +134,82 @@ void merge_input_config(struct input_config *dst, struct input_config *src) {
}
}
static void merge_wildcard_on_all ( struct input_config * wildcard ) {
static bool validate_xkb_merge ( struct input_config * dest ,
struct input_config * src , char * * xkb_error ) {
struct input_config * temp = new_input_config ( " temp " ) ;
if ( dest ) {
merge_input_config ( temp , dest ) ;
}
merge_input_config ( temp , src ) ;
struct xkb_keymap * keymap = sway_keyboard_compile_keymap ( temp , xkb_error ) ;
free_input_config ( temp ) ;
if ( ! keymap ) {
return false ;
}
xkb_keymap_unref ( keymap ) ;
return true ;
}
static bool validate_wildcard_on_all ( struct input_config * wildcard ,
char * * error ) {
for ( int i = 0 ; i < config - > input_configs - > length ; i + + ) {
struct input_config * ic = config - > input_configs - > items [ i ] ;
if ( strcmp ( wildcard - > identifier , ic - > identifier ) ! = 0 ) {
sway_log ( SWAY_DEBUG , " Merging input * config on %s " , ic - > identifier ) ;
merge_input_config ( ic , wildcard ) ;
sway_log ( SWAY_DEBUG , " Validating xkb merge of * on %s " ,
ic - > identifier ) ;
if ( ! validate_xkb_merge ( ic , wildcard , error ) ) {
return false ;
}
}
}
for ( int i = 0 ; i < config - > input_type_configs - > length ; i + + ) {
struct input_config * ic = config - > input_type_configs - > items [ i ] ;
sway_log ( SWAY_DEBUG , " Validating xkb merge of * config on %s " ,
ic - > identifier ) ;
if ( ! validate_xkb_merge ( ic , wildcard , error ) ) {
return false ;
}
}
return true ;
}
static void merge_wildcard_on_all ( struct input_config * wildcard ) {
for ( int i = 0 ; i < config - > input_configs - > length ; i + + ) {
struct input_config * ic = config - > input_configs - > items [ i ] ;
if ( strcmp ( wildcard - > identifier , ic - > identifier ) ! = 0 ) {
sway_log ( SWAY_DEBUG , " Merging input * config on %s " , ic - > identifier ) ;
merge_input_config ( ic , wildcard ) ;
}
}
for ( int i = 0 ; i < config - > input_type_configs - > length ; i + + ) {
struct input_config * ic = config - > input_type_configs - > items [ i ] ;
sway_log ( SWAY_DEBUG , " Merging input * config on %s " , ic - > identifier ) ;
merge_input_config ( ic , wildcard ) ;
}
}
static bool validate_type_on_existing ( struct input_config * type_wildcard ,
char * * error ) {
for ( int i = 0 ; i < config - > input_configs - > length ; i + + ) {
struct input_config * ic = config - > input_configs - > items [ i ] ;
if ( ic - > input_type = = NULL ) {
continue ;
}
if ( strcmp ( ic - > input_type , type_wildcard - > identifier + 5 ) = = 0 ) {
sway_log ( SWAY_DEBUG , " Validating merge of %s on %s " ,
type_wildcard - > identifier , ic - > identifier ) ;
if ( ! validate_xkb_merge ( ic , type_wildcard , error ) ) {
return false ;
}
}
}
return true ;
}
static void merge_type_on_existing ( struct input_config * type_wildcard ) {
@ -167,44 +228,59 @@ static void merge_type_on_existing(struct input_config *type_wildcard) {
}
}
struct input_config * store_input_config ( struct input_config * ic ) {
struct input_config * store_input_config ( struct input_config * ic ,
char * * error ) {
bool wildcard = strcmp ( ic - > identifier , " * " ) = = 0 ;
if ( wildcard & & error & & ! validate_wildcard_on_all ( ic , error ) ) {
return NULL ;
}
bool type = strncmp ( ic - > identifier , " type: " , strlen ( " type: " ) ) = = 0 ;
if ( type & & error & & ! validate_type_on_existing ( ic , error ) ) {
return NULL ;
}
list_t * config_list = type ? config - > input_type_configs
: config - > input_configs ;
struct input_config * current = NULL ;
bool new_current = false ;
int i = list_seq_find ( config_list , input_identifier_cmp , ic - > identifier ) ;
if ( i > = 0 ) {
current = config_list - > items [ i ] ;
}
i = list_seq_find ( config - > input_configs , input_identifier_cmp , " * " ) ;
if ( ! current & & i > = 0 ) {
current = new_input_config ( ic - > identifier ) ;
merge_input_config ( current , config - > input_configs - > items [ i ] ) ;
new_current = true ;
}
if ( error & & ! validate_xkb_merge ( current , ic , error ) ) {
if ( new_current ) {
free_input_config ( current ) ;
}
return NULL ;
}
if ( wildcard ) {
merge_wildcard_on_all ( ic ) ;
}
list_t * config_list = NULL ;
if ( strncmp ( ic - > identifier , " type: " , 5 ) = = 0 ) {
config_list = config - > input_type_configs ;
if ( type ) {
merge_type_on_existing ( ic ) ;
} else {
config_list = config - > input_configs ;
}
int i = list_seq_find ( config_list , input_identifier_cmp ,
ic - > identifier ) ;
if ( i > = 0 ) {
sway_log ( SWAY_DEBUG , " Merging on top of existing input config " ) ;
struct input_config * current = config_list - > items [ i ] ;
if ( current ) {
merge_input_config ( current , ic ) ;
free_input_config ( ic ) ;
ic = current ;
} else if ( ! wildcard ) {
sway_log ( SWAY_DEBUG , " Adding non-wildcard input config " ) ;
i = list_seq_find ( config - > input_configs , input_identifier_cmp , " * " ) ;
if ( i > = 0 ) {
sway_log ( SWAY_DEBUG , " Merging on top of input * config " ) ;
struct input_config * current = new_input_config ( ic - > identifier ) ;
merge_input_config ( current , config - > input_configs - > items [ i ] ) ;
merge_input_config ( current , ic ) ;
free_input_config ( ic ) ;
ic = current ;
}
}
if ( ! current | | new_current ) {
list_add ( config_list , ic ) ;
} else {
// New wildcard config. Just add it
sway_log ( SWAY_DEBUG , " Adding input * config " ) ;
list_add ( config - > input_configs , ic ) ;
}
sway_log ( SWAY_DEBUG , " Config stored for input %s " , ic - > identifier ) ;