2013-01-28 05:06:42 +00:00
/*
Copyright 2012 , 2013 Jun Wako < wakojun @ gmail . com >
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2012-12-15 17:32:07 +00:00
# include "host.h"
# include "keycode.h"
# include "keyboard.h"
# include "mousekey.h"
# include "command.h"
# include "debug.h"
2013-03-11 16:07:06 +00:00
# include "led.h"
2013-04-02 08:44:24 +00:00
# include "action_layer.h"
2013-03-28 15:56:34 +00:00
# include "action_tapping.h"
2013-03-21 05:42:40 +00:00
# include "action_oneshot.h"
2013-02-25 06:30:37 +00:00
# include "action_macro.h"
# include "action.h"
2012-12-15 17:32:07 +00:00
2013-01-26 17:42:48 +00:00
void action_exec ( keyevent_t event )
{
if ( ! IS_NOEVENT ( event ) ) {
2013-01-29 01:40:43 +00:00
debug ( " \n ---- action_exec: start ----- \n " ) ;
debug ( " EVENT: " ) ; debug_event ( event ) ; debug ( " \n " ) ;
2013-01-26 17:42:48 +00:00
}
keyrecord_t record = { . event = event } ;
2013-03-19 15:28:13 +00:00
# ifndef NO_ACTION_TAPPING
2013-03-28 15:56:34 +00:00
action_tapping_process ( record ) ;
2013-03-19 15:28:13 +00:00
# else
process_action ( & record ) ;
if ( ! IS_NOEVENT ( record . event ) ) {
debug ( " processed: " ) ; debug_record ( record ) ; debug ( " \n " ) ;
}
# endif
2013-01-15 10:04:58 +00:00
}
2013-03-28 15:56:34 +00:00
void process_action ( keyrecord_t * record )
2013-01-13 01:24:20 +00:00
{
2013-01-26 17:42:48 +00:00
keyevent_t event = record - > event ;
2013-04-02 07:09:43 +00:00
# ifndef NO_ACTION_TAPPING
2013-02-26 07:27:09 +00:00
uint8_t tap_count = record - > tap . count ;
2013-04-02 07:09:43 +00:00
# endif
2013-01-26 17:42:48 +00:00
2013-01-20 06:03:07 +00:00
if ( IS_NOEVENT ( event ) ) { return ; }
2013-02-20 02:16:13 +00:00
action_t action = layer_switch_get_action ( event . key ) ;
debug ( " ACTION: " ) ; debug_action ( action ) ;
2013-04-02 07:09:43 +00:00
# ifndef NO_ACTION_LAYER
debug ( " layer_state: " ) ; layer_debug ( ) ;
debug ( " default_layer_state: " ) ; default_layer_debug ( ) ;
# endif
debug ( " \n " ) ;
2012-12-15 17:32:07 +00:00
switch ( action . kind . id ) {
2013-01-13 01:24:20 +00:00
/* Key and Mods */
2012-12-15 17:32:07 +00:00
case ACT_LMODS :
case ACT_RMODS :
2013-01-27 07:38:19 +00:00
{
uint8_t mods = ( action . kind . id = = ACT_LMODS ) ? action . key . mods :
action . key . mods < < 4 ;
if ( event . pressed ) {
if ( mods ) {
host_add_mods ( mods ) ;
host_send_keyboard_report ( ) ;
}
register_code ( action . key . code ) ;
} else {
2013-04-04 07:29:44 +00:00
unregister_code ( action . key . code ) ;
if ( mods ) {
2013-01-27 07:38:19 +00:00
host_del_mods ( mods ) ;
host_send_keyboard_report ( ) ;
}
2013-01-13 01:24:20 +00:00
}
2012-12-15 17:32:07 +00:00
}
break ;
2013-03-19 15:28:13 +00:00
# ifndef NO_ACTION_TAPPING
2013-01-15 10:04:58 +00:00
case ACT_LMODS_TAP :
2013-01-20 06:03:07 +00:00
case ACT_RMODS_TAP :
{
2013-01-27 07:38:19 +00:00
uint8_t mods = ( action . kind . id = = ACT_LMODS_TAP ) ? action . key . mods :
action . key . mods < < 4 ;
2013-04-02 07:09:43 +00:00
switch ( action . layer_tap . code ) {
2013-03-21 05:42:40 +00:00
# ifndef NO_ACTION_ONESHOT
2013-01-27 07:38:19 +00:00
case 0x00 :
// Oneshot modifier
if ( event . pressed ) {
if ( tap_count = = 0 ) {
debug ( " MODS_TAP: Oneshot: add_mods \n " ) ;
add_mods ( mods ) ;
}
else if ( tap_count = = 1 ) {
debug ( " MODS_TAP: Oneshot: start \n " ) ;
2013-03-21 05:42:40 +00:00
oneshot_start ( mods ) ;
2013-01-27 07:38:19 +00:00
}
2013-02-01 05:48:11 +00:00
else if ( tap_count = = TAPPING_TOGGLE ) {
2013-01-27 07:38:19 +00:00
debug ( " MODS_TAP: Oneshot: toggle \n " ) ;
oneshot_toggle ( ) ;
}
else {
debug ( " MODS_TAP: Oneshot: cancel&add_mods \n " ) ;
// double tap cancels oneshot and works as normal modifier.
oneshot_cancel ( ) ;
add_mods ( mods ) ;
}
2013-01-17 02:46:38 +00:00
} else {
2013-01-27 07:38:19 +00:00
if ( tap_count = = 0 ) {
debug ( " MODS_TAP: Oneshot: cancel/del_mods \n " ) ;
2013-02-14 06:22:59 +00:00
// cancel oneshot on hold
2013-01-27 07:38:19 +00:00
oneshot_cancel ( ) ;
del_mods ( mods ) ;
}
else if ( tap_count = = 1 ) {
debug ( " MODS_TAP: Oneshot: del_mods \n " ) ;
// retain Oneshot
del_mods ( mods ) ;
}
else {
debug ( " MODS_TAP: Oneshot: del_mods \n " ) ;
// cancel Mods
del_mods ( mods ) ;
}
2013-01-17 02:46:38 +00:00
}
2013-01-27 07:38:19 +00:00
break ;
2013-03-21 05:42:40 +00:00
# endif
2013-01-27 07:38:19 +00:00
default :
if ( event . pressed ) {
if ( tap_count > 0 ) {
2013-03-28 15:56:34 +00:00
if ( record - > tap . interrupted ) {
2013-01-27 07:38:19 +00:00
debug ( " MODS_TAP: Tap: Cancel: add_mods \n " ) ;
// ad hoc: set 0 to cancel tap
2013-02-26 07:27:09 +00:00
record - > tap . count = 0 ;
2013-01-27 07:38:19 +00:00
add_mods ( mods ) ;
} else {
debug ( " MODS_TAP: Tap: register_code \n " ) ;
register_code ( action . key . code ) ;
}
} else {
debug ( " MODS_TAP: No tap: add_mods \n " ) ;
add_mods ( mods ) ;
}
} else {
if ( tap_count > 0 ) {
debug ( " MODS_TAP: Tap: unregister_code \n " ) ;
unregister_code ( action . key . code ) ;
} else {
debug ( " MODS_TAP: No tap: add_mods \n " ) ;
del_mods ( mods ) ;
}
}
break ;
2013-01-15 10:04:58 +00:00
}
}
2013-01-09 13:33:33 +00:00
break ;
2013-03-19 15:28:13 +00:00
# endif
# ifdef EXTRAKEY_ENABLE
2013-01-13 01:24:20 +00:00
/* other HID usage */
2013-01-09 13:33:33 +00:00
case ACT_USAGE :
switch ( action . usage . page ) {
2013-02-07 15:50:51 +00:00
case PAGE_SYSTEM :
2012-12-15 17:32:07 +00:00
if ( event . pressed ) {
2013-01-09 13:33:33 +00:00
host_system_send ( action . usage . code ) ;
2012-12-15 17:32:07 +00:00
} else {
2013-01-09 13:33:33 +00:00
host_system_send ( 0 ) ;
2012-12-15 17:32:07 +00:00
}
break ;
2013-02-07 15:50:51 +00:00
case PAGE_CONSUMER :
2013-01-09 13:33:33 +00:00
if ( event . pressed ) {
host_consumer_send ( action . usage . code ) ;
} else {
host_consumer_send ( 0 ) ;
}
2012-12-15 17:32:07 +00:00
break ;
2013-01-09 13:33:33 +00:00
}
break ;
2013-03-19 15:28:13 +00:00
# endif
# ifdef MOUSEKEY_ENABLE
2013-01-13 01:24:20 +00:00
/* Mouse key */
2013-01-09 13:33:33 +00:00
case ACT_MOUSEKEY :
if ( event . pressed ) {
mousekey_on ( action . key . code ) ;
mousekey_send ( ) ;
} else {
mousekey_off ( action . key . code ) ;
mousekey_send ( ) ;
}
break ;
2013-03-19 15:28:13 +00:00
# endif
2013-03-31 13:47:19 +00:00
# ifndef NO_ACTION_LAYER
case ACT_LAYER :
2013-04-02 07:09:43 +00:00
if ( action . layer_bitop . on = = 0 ) {
/* Default Layer Bitwise Operation */
if ( ! event . pressed ) {
uint8_t shift = action . layer_bitop . part * 4 ;
uint32_t bits = ( ( uint32_t ) action . layer_bitop . bits ) < < shift ;
uint32_t mask = ( action . layer_bitop . xbit ) ? ~ ( ( ( uint32_t ) 0xf ) < < shift ) : 0 ;
switch ( action . layer_bitop . op ) {
case OP_BIT_AND : default_layer_and ( bits | mask ) ; break ;
case OP_BIT_OR : default_layer_or ( bits | mask ) ; break ;
case OP_BIT_XOR : default_layer_xor ( bits | mask ) ; break ;
case OP_BIT_SET : default_layer_and ( mask ) ; default_layer_or ( bits ) ; break ;
2013-02-20 06:52:32 +00:00
}
2013-04-02 07:09:43 +00:00
}
} else {
/* Layer Bitwise Operation */
if ( event . pressed ? ( action . layer_bitop . on & ON_PRESS ) :
( action . layer_bitop . on & ON_RELEASE ) ) {
uint8_t shift = action . layer_bitop . part * 4 ;
uint32_t bits = ( ( uint32_t ) action . layer_bitop . bits ) < < shift ;
uint32_t mask = ( action . layer_bitop . xbit ) ? ~ ( ( ( uint32_t ) 0xf ) < < shift ) : 0 ;
switch ( action . layer_bitop . op ) {
case OP_BIT_AND : layer_and ( bits | mask ) ; break ;
case OP_BIT_OR : layer_or ( bits | mask ) ; break ;
case OP_BIT_XOR : layer_xor ( bits | mask ) ; break ;
case OP_BIT_SET : layer_and ( mask ) ; layer_or ( bits ) ; break ;
2013-02-07 15:50:51 +00:00
}
2013-04-02 07:09:43 +00:00
}
}
break ;
# ifndef NO_ACTION_TAPPING
case ACT_LAYER_TAP :
case ACT_LAYER_TAP1 :
switch ( action . layer_tap . code ) {
case OP_TAP_TOGGLE :
/* tap toggle */
2013-01-28 02:30:23 +00:00
if ( event . pressed ) {
2013-01-28 05:06:42 +00:00
if ( tap_count < TAPPING_TOGGLE ) {
2013-04-02 07:09:43 +00:00
layer_invert ( action . layer_tap . val ) ;
2013-01-28 02:30:23 +00:00
}
} else {
2013-02-20 02:16:13 +00:00
if ( tap_count < = TAPPING_TOGGLE ) {
2013-04-02 07:09:43 +00:00
layer_invert ( action . layer_tap . val ) ;
2013-01-28 02:30:23 +00:00
}
}
2012-12-15 17:32:07 +00:00
break ;
2013-04-02 07:09:43 +00:00
case OP_ON_OFF :
event . pressed ? layer_on ( action . layer_tap . val ) :
layer_off ( action . layer_tap . val ) ;
2013-01-09 13:33:33 +00:00
break ;
2013-04-02 07:09:43 +00:00
case OP_OFF_ON :
event . pressed ? layer_off ( action . layer_tap . val ) :
layer_on ( action . layer_tap . val ) ;
2013-02-14 06:22:59 +00:00
break ;
2013-04-02 07:09:43 +00:00
case OP_SET_CLEAR :
event . pressed ? layer_move ( action . layer_tap . val ) :
layer_clear ( ) ;
2013-02-14 06:22:59 +00:00
break ;
2013-01-09 13:33:33 +00:00
default :
2013-04-02 07:09:43 +00:00
/* tap key */
2013-01-09 13:33:33 +00:00
if ( event . pressed ) {
2013-02-20 07:53:55 +00:00
if ( tap_count > 0 ) {
2013-02-20 02:16:13 +00:00
debug ( " KEYMAP_TAP_KEY: Tap: register_code \n " ) ;
2013-04-02 07:09:43 +00:00
register_code ( action . layer_tap . code ) ;
2013-01-20 06:03:07 +00:00
} else {
2013-02-20 07:53:55 +00:00
debug ( " KEYMAP_TAP_KEY: No tap: On on press \n " ) ;
2013-04-02 07:09:43 +00:00
layer_on ( action . layer_tap . val ) ;
2013-01-09 13:33:33 +00:00
}
} else {
2013-02-20 07:53:55 +00:00
if ( tap_count > 0 ) {
2013-02-20 02:16:13 +00:00
debug ( " KEYMAP_TAP_KEY: Tap: unregister_code \n " ) ;
2013-04-02 07:09:43 +00:00
unregister_code ( action . layer_tap . code ) ;
2013-01-20 06:03:07 +00:00
} else {
2013-02-20 07:53:55 +00:00
debug ( " KEYMAP_TAP_KEY: No tap: Off on release \n " ) ;
2013-04-02 07:09:43 +00:00
layer_off ( action . layer_tap . val ) ;
2013-01-09 13:33:33 +00:00
}
2012-12-15 17:32:07 +00:00
}
break ;
}
2013-01-28 02:30:23 +00:00
break ;
2013-04-02 07:09:43 +00:00
# endif
2013-03-19 15:26:01 +00:00
# endif
2013-01-13 01:24:20 +00:00
/* Extentions */
2013-03-19 15:37:32 +00:00
# ifndef NO_ACTION_MACRO
2012-12-15 17:32:07 +00:00
case ACT_MACRO :
2013-02-25 06:30:37 +00:00
action_macro_play ( action_get_macro ( record , action . func . id , action . func . opt ) ) ;
2013-01-23 14:53:51 +00:00
break ;
2013-03-19 15:37:32 +00:00
# endif
2012-12-15 17:32:07 +00:00
case ACT_COMMAND :
2013-01-23 14:53:51 +00:00
break ;
2013-03-19 15:37:32 +00:00
# ifndef NO_ACTION_FUNCTION
2012-12-15 17:32:07 +00:00
case ACT_FUNCTION :
2013-02-13 02:47:19 +00:00
action_function ( record , action . func . id , action . func . opt ) ;
2013-01-23 14:53:51 +00:00
break ;
2013-03-19 15:37:32 +00:00
# endif
2012-12-15 17:32:07 +00:00
default :
break ;
}
2013-01-13 01:24:20 +00:00
}
2013-03-21 06:24:48 +00:00
/*
* Utilities for actions .
*/
void register_code ( uint8_t code )
{
if ( code = = KC_NO ) {
return ;
}
# ifdef CAPSLOCK_LOCKING_ENABLE
else if ( KC_LOCKING_CAPS = = code ) {
# ifdef CAPSLOCK_LOCKING_RESYNC_ENABLE
// Resync: ignore if caps lock already is on
if ( host_keyboard_leds ( ) & ( 1 < < USB_LED_CAPS_LOCK ) ) return ;
# endif
host_add_key ( KC_CAPSLOCK ) ;
host_send_keyboard_report ( ) ;
host_del_key ( KC_CAPSLOCK ) ;
host_send_keyboard_report ( ) ;
}
# endif
else if IS_KEY ( code ) {
// TODO: should push command_proc out of this block?
if ( command_proc ( code ) ) return ;
# ifndef NO_ACTION_ONESHOT
if ( oneshot_state . mods & & ! oneshot_state . disabled ) {
uint8_t tmp_mods = host_get_mods ( ) ;
host_add_mods ( oneshot_state . mods ) ;
host_add_key ( code ) ;
host_send_keyboard_report ( ) ;
host_set_mods ( tmp_mods ) ;
oneshot_cancel ( ) ;
} else
# endif
{
host_add_key ( code ) ;
host_send_keyboard_report ( ) ;
}
}
else if IS_MOD ( code ) {
host_add_mods ( MOD_BIT ( code ) ) ;
host_send_keyboard_report ( ) ;
}
}
void unregister_code ( uint8_t code )
{
if ( code = = KC_NO ) {
return ;
}
# ifdef CAPSLOCK_LOCKING_ENABLE
else if ( KC_LOCKING_CAPS = = code ) {
# ifdef CAPSLOCK_LOCKING_RESYNC_ENABLE
// Resync: ignore if caps lock already is off
if ( ! ( host_keyboard_leds ( ) & ( 1 < < USB_LED_CAPS_LOCK ) ) ) return ;
# endif
host_add_key ( KC_CAPSLOCK ) ;
host_send_keyboard_report ( ) ;
host_del_key ( KC_CAPSLOCK ) ;
host_send_keyboard_report ( ) ;
}
# endif
else if IS_KEY ( code ) {
host_del_key ( code ) ;
host_send_keyboard_report ( ) ;
}
else if IS_MOD ( code ) {
host_del_mods ( MOD_BIT ( code ) ) ;
host_send_keyboard_report ( ) ;
}
}
void add_mods ( uint8_t mods )
{
if ( mods ) {
host_add_mods ( mods ) ;
host_send_keyboard_report ( ) ;
}
}
void del_mods ( uint8_t mods )
{
if ( mods ) {
host_del_mods ( mods ) ;
host_send_keyboard_report ( ) ;
}
}
void set_mods ( uint8_t mods )
{
host_set_mods ( mods ) ;
host_send_keyboard_report ( ) ;
}
void clear_keyboard ( void )
{
host_clear_mods ( ) ;
clear_keyboard_but_mods ( ) ;
}
void clear_keyboard_but_mods ( void )
{
host_clear_keys ( ) ;
host_send_keyboard_report ( ) ;
# ifdef MOUSEKEY_ENABLE
mousekey_clear ( ) ;
mousekey_send ( ) ;
# endif
# ifdef EXTRAKEY_ENABLE
host_system_send ( 0 ) ;
host_consumer_send ( 0 ) ;
# endif
}
bool sending_anykey ( void )
{
return ( host_has_anykey ( ) | | host_mouse_in_use ( ) | |
host_last_sysytem_report ( ) | | host_last_consumer_report ( ) ) ;
}
bool is_tap_key ( key_t key )
{
action_t action = layer_switch_get_action ( key ) ;
switch ( action . kind . id ) {
case ACT_LMODS_TAP :
case ACT_RMODS_TAP :
2013-04-02 07:09:43 +00:00
case ACT_LAYER_TAP :
case ACT_LAYER_TAP1 :
2013-03-21 06:24:48 +00:00
return true ;
case ACT_MACRO :
case ACT_FUNCTION :
if ( action . func . opt & FUNC_TAP ) { return true ; }
return false ;
}
return false ;
}
/*
* debug print
*/
2013-03-28 15:56:34 +00:00
void debug_event ( keyevent_t event )
2013-03-21 06:24:48 +00:00
{
debug_hex16 ( ( event . key . row < < 8 ) | event . key . col ) ;
if ( event . pressed ) debug ( " d( " ) ; else debug ( " u( " ) ;
debug_dec ( event . time ) ; debug ( " ) " ) ;
}
2013-03-28 15:56:34 +00:00
void debug_record ( keyrecord_t record )
2013-03-21 06:24:48 +00:00
{
2013-03-28 15:56:34 +00:00
debug_event ( record . event ) ;
# ifndef NO_ACTION_TAPPING
debug ( " : " ) ; debug_dec ( record . tap . count ) ;
2013-03-21 06:24:48 +00:00
if ( record . tap . interrupted ) debug ( " - " ) ;
2013-03-28 15:56:34 +00:00
# endif
2013-03-21 06:24:48 +00:00
}
2013-03-28 15:56:34 +00:00
void debug_action ( action_t action )
2013-03-21 06:24:48 +00:00
{
switch ( action . kind . id ) {
case ACT_LMODS : debug ( " ACT_LMODS " ) ; break ;
case ACT_RMODS : debug ( " ACT_RMODS " ) ; break ;
case ACT_LMODS_TAP : debug ( " ACT_LMODS_TAP " ) ; break ;
case ACT_RMODS_TAP : debug ( " ACT_RMODS_TAP " ) ; break ;
case ACT_USAGE : debug ( " ACT_USAGE " ) ; break ;
case ACT_MOUSEKEY : debug ( " ACT_MOUSEKEY " ) ; break ;
2013-03-31 13:47:19 +00:00
case ACT_LAYER : debug ( " ACT_LAYER " ) ; break ;
2013-04-02 07:09:43 +00:00
case ACT_LAYER_TAP : debug ( " ACT_LAYER_TAP " ) ; break ;
case ACT_LAYER_TAP1 : debug ( " ACT_LAYER_TAP1 " ) ; break ;
2013-03-21 06:24:48 +00:00
case ACT_MACRO : debug ( " ACT_MACRO " ) ; break ;
case ACT_COMMAND : debug ( " ACT_COMMAND " ) ; break ;
case ACT_FUNCTION : debug ( " ACT_FUNCTION " ) ; break ;
default : debug ( " UNKNOWN " ) ; break ;
}
debug ( " [ " ) ;
debug_hex4 ( action . kind . param > > 8 ) ;
debug ( " : " ) ;
debug_hex8 ( action . kind . param & 0xff ) ;
debug ( " ] " ) ;
}