@ -9,86 +9,112 @@
 
			
		
	
		
			
				
					# include  "sway/commands.h"  
			
		
	
		
			
				
					# include  "log.h"  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					/**
  
			
		
	
		
			
				
					 *  Remove  all  key  ids  associated  to  a  keycode  from  the  list  of  pressed  keys 
 
			
		
	
		
			
				
					 */ 
 
			
		
	
		
			
				
					static  void  state_erase_key ( struct  sway_shortcut_state  * state ,  
			
		
	
		
			
				
							uint32_t  keycode )  { 
 
			
		
	
		
			
				
						size_t  j  =  0 ; 
 
			
		
	
		
			
				
						for  ( size_t  i  =  0 ;  i  <  state - > npressed ;  + + i )  { 
 
			
		
	
		
			
				
							if  ( i  >  j )  { 
 
			
		
	
		
			
				
								state - > pressed_keys [ j ]  =  state - > pressed_keys [ i ] ; 
 
			
		
	
		
			
				
								state - > pressed_keycodes [ j ]  =  state - > pressed_keycodes [ i ] ; 
 
			
		
	
		
			
				
							} 
 
			
		
	
		
			
				
							if  ( state - > pressed_keycodes [ i ]  ! =  keycode )  { 
 
			
		
	
		
			
				
								+ + j ; 
 
			
		
	
		
			
				
							} 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
						while ( state - > npressed  >  j )  { 
 
			
		
	
		
			
				
							- - state - > npressed ; 
 
			
		
	
		
			
				
							state - > pressed_keys [ state - > npressed ]  =  0 ; 
 
			
		
	
		
			
				
							state - > pressed_keycodes [ state - > npressed ]  =  0 ; 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					/**
  
			
		
	
		
			
				
					 *  Add  a  key  id  ( with  associated  keycode )  to  the  list  of  pressed  keys , 
 
			
		
	
		
			
				
					 *  if  the  list  is  not  full . 
 
			
		
	
		
			
				
					 */ 
 
			
		
	
		
			
				
					static  void  state_add_key ( struct  sway_shortcut_state  * state ,  
			
		
	
		
			
				
							uint32_t  keycode ,  uint32_t  key_id )  { 
 
			
		
	
		
			
				
						if  ( state - > npressed  > =  SWAY_KEYBOARD_PRESSED_KEYS_CAP )  { 
 
			
		
	
		
			
				
							return ; 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
						size_t  i  =  0 ; 
 
			
		
	
		
			
				
						while  ( i  <  state - > npressed  & &  state - > pressed_keys [ i ]  <  key_id )  { 
 
			
		
	
		
			
				
							+ + i ; 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
						size_t  j  =  state - > npressed ; 
 
			
		
	
		
			
				
						while  ( j  >  i )  { 
 
			
		
	
		
			
				
							state - > pressed_keys [ j ]  =  state - > pressed_keys [ j  -  1 ] ; 
 
			
		
	
		
			
				
							state - > pressed_keycodes [ j ]  =  state - > pressed_keycodes [ j  -  1 ] ; 
 
			
		
	
		
			
				
							- - j ; 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
						state - > pressed_keys [ i ]  =  key_id ; 
 
			
		
	
		
			
				
						state - > pressed_keycodes [ i ]  =  keycode ; 
 
			
		
	
		
			
				
						state - > npressed + + ; 
 
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					/**
  
			
		
	
		
			
				
					 *  Update  the  shortcut  model  state  in  response  to  new  input 
 
			
		
	
		
			
				
					 */ 
 
			
		
	
		
			
				
					static  void  update_shortcut_state ( struct  sway_shortcut_state  * state ,  
			
		
	
		
			
				
							struct  wlr_event_keyboard_key  * event ,  uint32_t  new_key , 
 
			
		
	
		
			
				
							bool  last_key_was_a_modifier )  { 
 
			
		
	
		
			
				
							uint32_t  raw_modifiers )  { 
 
			
		
	
		
			
				
						bool  last_key_was_a_modifier  =  raw_modifiers  ! =  state - > last_raw_modifiers ; 
 
			
		
	
		
			
				
						state - > last_raw_modifiers  =  raw_modifiers ; 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						if  ( event - > state  = =  WLR_KEY_PRESSED )  { 
 
			
		
	
		
			
				
							if  ( last_key_was_a_modifier  & &  state - > last_key_index  > =  0 )  { 
 
			
		
	
		
			
				
							if  ( last_key_was_a_modifier  & &  state - > last_key code )  { 
 
			
		
	
		
			
				
								// Last pressed key before this one was a modifier
 
 
			
		
	
		
			
				
								state - > pressed_keycodes [ state - > last_key_index ]  =  0 ; 
 
			
		
	
		
			
				
								state - > pressed_keys [ state - > last_key_index ]  =  0 ; 
 
			
		
	
		
			
				
								state - > last_key_index  =  - 1 ; 
 
			
		
	
		
			
				
								state_erase_key ( state ,  state - > last_keycode ) ; 
 
			
		
	
		
			
				
							} 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
							// Add current key to set; there may be duplicates
 
 
			
		
	
		
			
				
							for  ( size_t  i  =  0 ;  i  <  SWAY_KEYBOARD_PRESSED_KEYS_CAP ;  + + i )  { 
 
			
		
	
		
			
				
								if  ( ! state - > pressed_keys [ i ] )  { 
 
			
		
	
		
			
				
									state - > pressed_keys [ i ]  =  new_key ; 
 
			
		
	
		
			
				
									state - > pressed_keycodes [ i ]  =  event - > keycode ; 
 
			
		
	
		
			
				
									state - > last_key_index  =  i ; 
 
			
		
	
		
			
				
									break ; 
 
			
		
	
		
			
				
								} 
 
			
		
	
		
			
				
							} 
 
			
		
	
		
			
				
							state_add_key ( state ,  event - > keycode ,  new_key ) ; 
 
			
		
	
		
			
				
							state - > last_keycode  =  event - > keycode ; 
 
			
		
	
		
			
				
						}  else  { 
 
			
		
	
		
			
				
							for  ( size_t  i  =  0 ;  i  <  SWAY_KEYBOARD_PRESSED_KEYS_CAP ;  + + i )  { 
 
			
		
	
		
			
				
								// The same keycode may match multiple keysyms.
 
 
			
		
	
		
			
				
								if  ( state - > pressed_keycodes [ i ]  = =  event - > keycode )  { 
 
			
		
	
		
			
				
									state - > pressed_keys [ i ]  =  0 ; 
 
			
		
	
		
			
				
									state - > pressed_keycodes [ i ]  =  0 ; 
 
			
		
	
		
			
				
								} 
 
			
		
	
		
			
				
							} 
 
			
		
	
		
			
				
							state_erase_key ( state ,  event - > keycode ) ; 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					/**
  
			
		
	
		
			
				
					 * 
 
			
		
	
		
			
				
					 *  Returns  a  binding  which  matches  the  shortcut  model  state  ( ignoring  the 
 
			
		
	
		
			
				
					 *  ` release `  flag ) . 
 
			
		
	
		
			
				
					 *  If  one  exists ,  finds  a  binding  which  matches  the  shortcut  model  state , 
 
			
		
	
		
			
				
					 *  current  modifiers ,  release  state ,  and  locked  state . 
 
			
		
	
		
			
				
					 */ 
 
			
		
	
		
			
				
					static  struct  sway_binding  * get_active_binding (  
			
		
	
		
			
				
							struct  sway_shortcut_state  * state ,  list_t  * bindings , 
 
			
		
	
		
			
				
							uint32_t  modifiers ,  bool  locked )  { 
 
			
		
	
		
			
				
						int  npressed_keys  =  0 ; 
 
			
		
	
		
			
				
						for  ( size_t  i  =  0 ;  i  <  SWAY_KEYBOARD_PRESSED_KEYS_CAP ;  + + i )  { 
 
			
		
	
		
			
				
							if  ( state - > pressed_keys [ i ] )  { 
 
			
		
	
		
			
				
								+ + npressed_keys ; 
 
			
		
	
		
			
				
							} 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
					static  void  get_active_binding ( const  struct  sway_shortcut_state  * state ,  
			
		
	
		
			
				
							list_t  * bindings ,  struct  sway_binding  * * current_binding , 
 
			
		
	
		
			
				
							uint32_t  modifiers ,  bool  release ,  bool  locked )  { 
 
			
		
	
		
			
				
						for  ( int  i  =  0 ;  i  <  bindings - > length ;  + + i )  { 
 
			
		
	
		
			
				
							struct  sway_binding  * binding  =  bindings - > items [ i ] ; 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
							if  ( modifiers  ^  binding - > modifiers  | | 
 
			
		
	
		
			
				
									npressed_keys  ! =  binding - > keys - > length  | | 
 
			
		
	
		
			
				
									locked  >  binding - > locked )  { 
 
			
		
	
		
			
				
									state - > npressed  ! =  ( size_t ) binding - > keys - > length  | | 
 
			
		
	
		
			
				
									locked  >  binding - > locked  | | 
 
			
		
	
		
			
				
									release  ! =  binding - > release )  { 
 
			
		
	
		
			
				
								continue ; 
 
			
		
	
		
			
				
							} 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
							bool  match  =  true ; 
 
			
		
	
		
			
				
							for  ( int j  =  0 ;  j  <  binding - > keys - > length ;  + + j  )  { 
 
			
		
	
		
			
				
							for  ( size_t j  =  0 ;  j  <  state - > npressed ;  j + +  )  { 
 
			
		
	
		
			
				
								uint32_t  key  =  * ( uint32_t  * ) binding - > keys - > items [ j ] ; 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
								bool  key_found  =  false ; 
 
			
		
	
		
			
				
								for  ( int  k  =  0 ;  k  <  SWAY_KEYBOARD_PRESSED_KEYS_CAP ;  + + k )  { 
 
			
		
	
		
			
				
									if  ( state - > pressed_keys [ k ]  = =  key )  { 
 
			
		
	
		
			
				
										key_found  =  true ; 
 
			
		
	
		
			
				
										break ; 
 
			
		
	
		
			
				
									} 
 
			
		
	
		
			
				
								} 
 
			
		
	
		
			
				
								if  ( ! key_found )  { 
 
			
		
	
		
			
				
								if  ( key  ! =  state - > pressed_keys [ j ] )  { 
 
			
		
	
		
			
				
									match  =  false ; 
 
			
		
	
		
			
				
									break ; 
 
			
		
	
		
			
				
								} 
 
			
		
	
		
			
				
							} 
 
			
		
	
		
			
				
							if  ( ! match )  { 
 
			
		
	
		
			
				
								continue ; 
 
			
		
	
		
			
				
							} 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
							if  ( match )  { 
 
			
		
	
		
			
				
								return  binding ; 
 
			
		
	
		
			
				
							if  ( * current_binding  & &  * current_binding  ! =  binding )  { 
 
			
		
	
		
			
				
								wlr_log ( L_DEBUG ,  " encountered duplicate bindings %d and %d " , 
 
			
		
	
		
			
				
										( * current_binding ) - > order ,  binding - > order ) ; 
 
			
		
	
		
			
				
							}  else  { 
 
			
		
	
		
			
				
								* current_binding  =  binding ; 
 
			
		
	
		
			
				
							} 
 
			
		
	
		
			
				
							return ; 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						return  NULL ; 
 
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					/**
  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -204,69 +230,65 @@ static void handle_keyboard_key(struct wl_listener *listener, void *data) {
 
			
		
	
		
			
				
						size_t  raw_keysyms_len  = 
 
			
		
	
		
			
				
							keyboard_keysyms_raw ( keyboard ,  keycode ,  & raw_keysyms ,  & raw_modifiers ) ; 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						struct  wlr_input_device  * device  = 
 
			
		
	
		
			
				
							keyboard - > seat_device - > input_device - > wlr_device ; 
 
			
		
	
		
			
				
						uint32_t  code_modifiers  =  wlr_keyboard_get_modifiers ( device - > keyboard ) ; 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						bool  last_key_was_a_modifier  =  code_modifiers  ! =  keyboard - > last_modifiers ; 
 
			
		
	
		
			
				
						keyboard - > last_modifiers  =  code_modifiers ; 
 
			
		
	
		
			
				
						uint32_t  code_modifiers  =  wlr_keyboard_get_modifiers ( wlr_device - > keyboard ) ; 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						// Update shortcut model state
 
 
			
		
	
		
			
				
						update_shortcut_state ( & keyboard - > state_keycodes ,  event , 
 
			
		
	
		
			
				
								( uint32_t ) keycode ,  last_key_was_a_modifier ) ; 
 
			
		
	
		
			
				
								( uint32_t ) keycode ,  code_modifiers ) ; 
 
			
		
	
		
			
				
						for  ( size_t  i  =  0 ;  i  <  translated_keysyms_len ;  + + i )  { 
 
			
		
	
		
			
				
							update_shortcut_state ( & keyboard - > state_keysyms_translated , 
 
			
		
	
		
			
				
									event ,  ( uint32_t ) translated_keysyms [ i ] , 
 
			
		
	
		
			
				
									last_key_was_a_modifier & &  i  = =  0  ) ; 
 
			
		
	
		
			
				
									code_modifiers ) ; 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
						for  ( size_t  i  =  0 ;  i  <  raw_keysyms_len ;  + + i )  { 
 
			
		
	
		
			
				
							update_shortcut_state ( & keyboard - > state_keysyms_raw , 
 
			
		
	
		
			
				
									event ,  ( uint32_t ) raw_keysyms [ i ] , 
 
			
		
	
		
			
				
									last_key_was_a_modifier & &  i  = =  0  ) ; 
 
			
		
	
		
			
				
									code_modifiers ) ; 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						// identify which binding should be executed.
 
 
			
		
	
		
			
				
						struct  sway_binding  * binding  =  get_active_binding ( 
 
			
		
	
		
			
				
								& keyboard - > state_keycodes , 
 
			
		
	
		
			
				
								config - > current_mode - > keycode_bindings , 
 
			
		
	
		
			
				
								code_modifiers ,  input_inhibited ) ; 
 
			
		
	
		
			
				
						struct  sway_binding  * translated_binding  =  get_active_binding ( 
 
			
		
	
		
			
				
								& keyboard - > state_keysyms_translated , 
 
			
		
	
		
			
				
								config - > current_mode - > keysym_bindings , 
 
			
		
	
		
			
				
								translated_modifiers ,  input_inhibited ) ; 
 
			
		
	
		
			
				
						if  ( translated_binding  & &  ! binding )  { 
 
			
		
	
		
			
				
							binding  =  translated_binding ; 
 
			
		
	
		
			
				
						}  else  if  ( binding  & &  translated_binding  & &  binding  ! =  translated_binding )  { 
 
			
		
	
		
			
				
							wlr_log ( L_DEBUG ,  " encountered duplicate bindings %d and %d " , 
 
			
		
	
		
			
				
								binding - > order ,  translated_binding - > order ) ; 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
						struct  sway_binding  * raw_binding  =  get_active_binding ( 
 
			
		
	
		
			
				
								& keyboard - > state_keysyms_raw , 
 
			
		
	
		
			
				
								config - > current_mode - > keysym_bindings , 
 
			
		
	
		
			
				
								raw_modifiers ,  input_inhibited ) ; 
 
			
		
	
		
			
				
						if  ( raw_binding  & &  ! binding )  { 
 
			
		
	
		
			
				
							binding  =  raw_binding ; 
 
			
		
	
		
			
				
						}  else  if  ( binding  & &  raw_binding  & &  binding  ! =  raw_binding )  { 
 
			
		
	
		
			
				
							wlr_log ( L_DEBUG ,  " encountered duplicate bindings %d and %d " , 
 
			
		
	
		
			
				
								binding - > order ,  raw_binding - > order ) ; 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						bool  handled  =  false ; 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						// Execute the identified binding if need be.
 
 
			
		
	
		
			
				
						if  ( keyboard - > held_binding  & &  binding  ! =  keyboard - > held_binding  & & 
 
			
		
	
		
			
				
						// Identify active release binding
 
 
			
		
	
		
			
				
						struct  sway_binding  * binding_released  =  NULL ; 
 
			
		
	
		
			
				
						get_active_binding ( & keyboard - > state_keycodes , 
 
			
		
	
		
			
				
								config - > current_mode - > keycode_bindings ,  & binding_released , 
 
			
		
	
		
			
				
								code_modifiers ,  true ,  input_inhibited ) ; 
 
			
		
	
		
			
				
						get_active_binding ( & keyboard - > state_keysyms_translated , 
 
			
		
	
		
			
				
								config - > current_mode - > keysym_bindings ,  & binding_released , 
 
			
		
	
		
			
				
								translated_modifiers ,  true ,  input_inhibited ) ; 
 
			
		
	
		
			
				
						get_active_binding ( & keyboard - > state_keysyms_raw , 
 
			
		
	
		
			
				
								config - > current_mode - > keysym_bindings ,  & binding_released , 
 
			
		
	
		
			
				
								raw_modifiers ,  true ,  input_inhibited ) ; 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						// Execute stored release binding once no longer active
 
 
			
		
	
		
			
				
						if  ( keyboard - > held_binding  & &  binding_released  ! =  keyboard - > held_binding  & & 
 
			
		
	
		
			
				
								event - > state  = =  WLR_KEY_RELEASED )  { 
 
			
		
	
		
			
				
							keyboard_execute_command ( keyboard ,  keyboard - > held_binding ) ; 
 
			
		
	
		
			
				
							handled  =  true ; 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
						if  ( binding  ! =  keyboard - > held_binding )  { 
 
			
		
	
		
			
				
						if  ( binding_released  ! =  keyboard - > held_binding )  { 
 
			
		
	
		
			
				
							keyboard - > held_binding  =  NULL ; 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
						if  ( binding  & &  event - > state  = =  WLR_KEY_PRESSED )  { 
 
			
		
	
		
			
				
							if  ( binding - > release )  { 
 
			
		
	
		
			
				
								keyboard - > held_binding  =  binding ; 
 
			
		
	
		
			
				
							}  else  { 
 
			
		
	
		
			
				
								keyboard_execute_command ( keyboard ,  binding ) ; 
 
			
		
	
		
			
				
						if  ( binding_released  & &  event - > state  = =  WLR_KEY_PRESSED )  { 
 
			
		
	
		
			
				
							keyboard - > held_binding  =  binding_released ; 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						// Identify and execute active pressed binding
 
 
			
		
	
		
			
				
						if  ( event - > state  = =  WLR_KEY_PRESSED )  { 
 
			
		
	
		
			
				
							struct  sway_binding  * binding_pressed  =  NULL ; 
 
			
		
	
		
			
				
							get_active_binding ( & keyboard - > state_keycodes , 
 
			
		
	
		
			
				
									config - > current_mode - > keycode_bindings ,  & binding_pressed , 
 
			
		
	
		
			
				
									code_modifiers ,  false ,  input_inhibited ) ; 
 
			
		
	
		
			
				
							get_active_binding ( & keyboard - > state_keysyms_translated , 
 
			
		
	
		
			
				
									config - > current_mode - > keysym_bindings ,  & binding_pressed , 
 
			
		
	
		
			
				
									translated_modifiers ,  false ,  input_inhibited ) ; 
 
			
		
	
		
			
				
							get_active_binding ( & keyboard - > state_keysyms_raw , 
 
			
		
	
		
			
				
									config - > current_mode - > keysym_bindings ,  & binding_pressed , 
 
			
		
	
		
			
				
									raw_modifiers ,  false ,  input_inhibited ) ; 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
							if  ( binding_pressed )  { 
 
			
		
	
		
			
				
								keyboard_execute_command ( keyboard ,  binding_pressed ) ; 
 
			
		
	
		
			
				
								handled  =  true ; 
 
			
		
	
		
			
				
							} 
 
			
		
	
		
			
				
						} 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -315,10 +337,6 @@ struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat,
 
			
		
	
		
			
				
						wl_list_init ( & keyboard - > keyboard_key . link ) ; 
 
			
		
	
		
			
				
						wl_list_init ( & keyboard - > keyboard_modifiers . link ) ; 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						keyboard - > state_keycodes . last_key_index  =  - 1 ; 
 
			
		
	
		
			
				
						keyboard - > state_keysyms_raw . last_key_index  =  - 1 ; 
 
			
		
	
		
			
				
						keyboard - > state_keysyms_translated . last_key_index  =  - 1 ; 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						return  keyboard ; 
 
			
		
	
		
			
				
					}