@ -34,11 +34,14 @@ void free_sway_binding(struct sway_binding *binding) {
*/
*/
static bool binding_key_compare ( struct sway_binding * binding_a ,
static bool binding_key_compare ( struct sway_binding * binding_a ,
struct sway_binding * binding_b ) {
struct sway_binding * binding_b ) {
if ( binding_a - > release ! = binding_b - > releas e) {
if ( binding_a - > type ! = binding_b - > typ e) {
return false ;
return false ;
}
}
if ( binding_a - > bindcode ! = binding_b - > bindcode ) {
uint32_t conflict_generating_flags = BINDING_RELEASE | BINDING_BORDER
| BINDING_CONTENTS | BINDING_TITLEBAR ;
if ( ( binding_a - > flags & conflict_generating_flags ) ! =
( binding_b - > flags & conflict_generating_flags ) ) {
return false ;
return false ;
}
}
@ -69,6 +72,66 @@ static int key_qsort_cmp(const void *keyp_a, const void *keyp_b) {
return ( key_a < key_b ) ? - 1 : ( ( key_a > key_b ) ? 1 : 0 ) ;
return ( key_a < key_b ) ? - 1 : ( ( key_a > key_b ) ? 1 : 0 ) ;
}
}
/**
* From a keycode , bindcode , or bindsym name and the most likely binding type ,
* identify the appropriate numeric value corresponding to the key . Return NULL
* and set * key_val if successful , otherwise return a specific error . Change
* the value of * type if the initial type guess was incorrect and if this
* was the first identified key .
*/
static struct cmd_results * identify_key ( const char * name , bool first_key ,
uint32_t * key_val , enum binding_input_type * type ) {
if ( * type = = BINDING_KEYCODE ) {
// check for keycode
xkb_keycode_t keycode = strtol ( name , NULL , 10 ) ;
if ( ! xkb_keycode_is_legal_ext ( keycode ) ) {
return cmd_results_new ( CMD_INVALID , " bindcode " ,
" Invalid keycode '%s' " , name ) ;
}
* key_val = keycode ;
} else {
// check for keysym
xkb_keysym_t keysym = xkb_keysym_from_name ( name ,
XKB_KEYSYM_CASE_INSENSITIVE ) ;
// Check for mouse binding
uint32_t button = 0 ;
if ( strncasecmp ( name , " button " , strlen ( " button " ) ) = = 0 & &
strlen ( name ) = = strlen ( " button0 " ) ) {
button = name [ strlen ( " button " ) ] - ' 1 ' + BTN_LEFT ;
}
if ( * type = = BINDING_KEYSYM ) {
if ( button ) {
if ( first_key ) {
* type = BINDING_MOUSE ;
* key_val = button ;
} else {
return cmd_results_new ( CMD_INVALID , " bindsym " ,
" Mixed button '%s' into key sequence " , name ) ;
}
} else if ( keysym ) {
* key_val = keysym ;
} else {
return cmd_results_new ( CMD_INVALID , " bindsym " ,
" Unknown key '%s' " , name ) ;
}
} else {
if ( button ) {
* key_val = button ;
} else if ( keysym ) {
return cmd_results_new ( CMD_INVALID , " bindsym " ,
" Mixed keysym '%s' into button sequence " , name ) ;
} else {
return cmd_results_new ( CMD_INVALID , " bindsym " ,
" Unknown button '%s' " , name ) ;
}
}
}
return NULL ;
}
static struct cmd_results * cmd_bindsym_or_bindcode ( int argc , char * * argv ,
static struct cmd_results * cmd_bindsym_or_bindcode ( int argc , char * * argv ,
bool bindcode ) {
bool bindcode ) {
const char * bindtype = bindcode ? " bindcode " : " bindsym " ;
const char * bindtype = bindcode ? " bindcode " : " bindsym " ;
@ -85,22 +148,34 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
}
}
binding - > keys = create_list ( ) ;
binding - > keys = create_list ( ) ;
binding - > modifiers = 0 ;
binding - > modifiers = 0 ;
binding - > release = false ;
binding - > flags = 0 ;
binding - > locked = false ;
binding - > type = bindcode ? BINDING_KEYCODE : BINDING_KEYSYM ;
binding - > bindcode = bindcode ;
bool exclude_titlebar = false ;
// Handle --release and --locked
// Handle --release and --locked
while ( argc > 0 ) {
while ( argc > 0 ) {
if ( strcmp ( " --release " , argv [ 0 ] ) = = 0 ) {
if ( strcmp ( " --release " , argv [ 0 ] ) = = 0 ) {
binding - > release = true ;
binding - > flags | = BINDING_RELEASE ;
} else if ( strcmp ( " --locked " , argv [ 0 ] ) = = 0 ) {
} else if ( strcmp ( " --locked " , argv [ 0 ] ) = = 0 ) {
binding - > locked = true ;
binding - > flags | = BINDING_LOCKED ;
} else if ( strcmp ( " --whole-window " , argv [ 0 ] ) = = 0 ) {
binding - > flags | = BINDING_BORDER | BINDING_CONTENTS | BINDING_TITLEBAR ;
} else if ( strcmp ( " --border " , argv [ 0 ] ) = = 0 ) {
binding - > flags | = BINDING_BORDER ;
} else if ( strcmp ( " --exclude-titlebar " , argv [ 0 ] ) = = 0 ) {
exclude_titlebar = true ;
} else {
} else {
break ;
break ;
}
}
argv + + ;
argv + + ;
argc - - ;
argc - - ;
}
}
if ( binding - > flags & ( BINDING_BORDER | BINDING_CONTENTS | BINDING_TITLEBAR )
| | exclude_titlebar ) {
binding - > type = BINDING_MOUSE ;
}
if ( argc < 2 ) {
if ( argc < 2 ) {
free_sway_binding ( binding ) ;
free_sway_binding ( binding ) ;
return cmd_results_new ( CMD_FAILURE , bindtype ,
return cmd_results_new ( CMD_FAILURE , bindtype ,
@ -119,64 +194,47 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
continue ;
continue ;
}
}
xkb_keycode_t keycode ;
// Identify the key and possibly change binding->type
xkb_keysym_t keysym ;
uint32_t key_val = 0 ;
if ( bindcode ) {
error = identify_key ( split - > items [ i ] , binding - > keys - > length = = 0 ,
// parse keycode
& key_val , & binding - > type ) ;
keycode = ( int ) strtol ( split - > items [ i ] , NULL , 10 ) ;
if ( error ) {
if ( ! xkb_keycode_is_legal_ext ( keycode ) ) {
error =
cmd_results_new ( CMD_INVALID , " bindcode " ,
" Invalid keycode '%s' " , ( char * ) split - > items [ i ] ) ;
free_sway_binding ( binding ) ;
free_sway_binding ( binding ) ;
list_free ( split ) ;
list_free ( split ) ;
return error ;
return error ;
}
}
} else {
// Check for xkb key
keysym = xkb_keysym_from_name ( split - > items [ i ] ,
XKB_KEYSYM_CASE_INSENSITIVE ) ;
// Check for mouse binding
if ( strncasecmp ( split - > items [ i ] , " button " , strlen ( " button " ) ) = = 0 & &
strlen ( split - > items [ i ] ) = = strlen ( " button0 " ) ) {
keysym = ( ( char * ) split - > items [ i ] ) [ strlen ( " button " ) ] - ' 1 ' + BTN_LEFT ;
}
if ( ! keysym ) {
struct cmd_results * ret = cmd_results_new ( CMD_INVALID , " bindsym " ,
" Unknown key '%s' " , ( char * ) split - > items [ i ] ) ;
free_sway_binding ( binding ) ;
free_flat_list ( split ) ;
return ret ;
}
}
uint32_t * key = calloc ( 1 , sizeof ( uint32_t ) ) ;
uint32_t * key = calloc ( 1 , sizeof ( uint32_t ) ) ;
if ( ! key ) {
if ( ! key ) {
free_sway_binding ( binding ) ;
free_sway_binding ( binding ) ;
free_flat_list ( split ) ;
free_flat_list ( split ) ;
return cmd_results_new ( CMD_FAILURE , bindtype ,
return cmd_results_new ( CMD_FAILURE , bindtype ,
" Unable to allocate binding " ) ;
" Unable to allocate binding key " ) ;
}
if ( bindcode ) {
* key = ( uint32_t ) keycode ;
} else {
* key = ( uint32_t ) keysym ;
}
}
* key = key_val ;
list_add ( binding - > keys , key ) ;
list_add ( binding - > keys , key ) ;
}
}
free_flat_list ( split ) ;
free_flat_list ( split ) ;
binding - > order = binding_order + + ;
binding - > order = binding_order + + ;
// refine region of interest for mouse binding once we are certain
// that this is one
if ( exclude_titlebar ) {
binding - > flags & = ~ BINDING_TITLEBAR ;
} else if ( binding - > type = = BINDING_MOUSE ) {
binding - > flags | = BINDING_TITLEBAR ;
}
// sort ascending
// sort ascending
list_qsort ( binding - > keys , key_qsort_cmp ) ;
list_qsort ( binding - > keys , key_qsort_cmp ) ;
list_t * mode_bindings ;
list_t * mode_bindings ;
if ( bindcode ) {
if ( bind ing- > type = = BINDING_KEYCODE ) {
mode_bindings = config - > current_mode - > keycode_bindings ;
mode_bindings = config - > current_mode - > keycode_bindings ;
} else {
} else if ( binding - > type = = BINDING_KEYSYM ) {
mode_bindings = config - > current_mode - > keysym_bindings ;
mode_bindings = config - > current_mode - > keysym_bindings ;
} else {
mode_bindings = config - > current_mode - > mouse_bindings ;
}
}
// overwrite the binding if it already exists
// overwrite the binding if it already exists