1use super::*;
2
3pub type KeyOutputs = Vec<HashMap<OsCode, Vec<OsCode>>>;
7
8pub(crate) fn create_key_outputs(
10 layers: &KLayers,
11 overrides: &Overrides,
12 chords_v2: &Option<ChordsV2<'static, KanataCustom>>,
13) -> KeyOutputs {
14 let mut outs = KeyOutputs::new();
15 for (layer_idx, layer) in layers.iter().enumerate() {
16 let mut layer_outputs = HashMap::default();
17 for (i, action) in layer[0].iter().enumerate() {
18 let osc_slot = match i.try_into() {
19 Ok(i) => i,
20 Err(_) => continue,
21 };
22 add_key_output_from_action_to_key_pos(osc_slot, action, &mut layer_outputs, overrides);
23 add_chordsv2_output_for_key_pos(
24 osc_slot,
25 layer_idx,
26 chords_v2,
27 &mut layer_outputs,
28 overrides,
29 );
30 }
31 outs.push(layer_outputs);
32 }
33 for layer_outs in outs.iter_mut() {
34 for keys_out in layer_outs.values_mut() {
35 keys_out.shrink_to_fit();
36 }
37 layer_outs.shrink_to_fit();
38 }
39 outs.shrink_to_fit();
40 outs
41}
42
43pub(crate) fn add_chordsv2_output_for_key_pos(
44 osc_slot: OsCode,
45 layer_idx: usize,
46 chords_v2: &Option<ChordsV2<'static, KanataCustom>>,
47 outputs: &mut HashMap<OsCode, Vec<OsCode>>,
48 overrides: &Overrides,
49) {
50 assert!(layer_idx <= usize::from(u16::MAX));
51 let Some(chords_v2) = chords_v2.as_ref() else {
52 return;
53 };
54 let Some(chords_for_key) = chords_v2.chords().mapping.get(&u16::from(osc_slot)) else {
55 return;
56 };
57 for chord in chords_for_key.chords.iter() {
58 if !chord.disabled_layers.contains(&(layer_idx as u16)) {
59 add_key_output_from_action_to_key_pos(osc_slot, chord.action, outputs, overrides);
60 }
61 }
62}
63
64pub(crate) fn add_key_output_from_action_to_key_pos(
65 osc_slot: OsCode,
66 action: &KanataAction,
67 outputs: &mut HashMap<OsCode, Vec<OsCode>>,
68 overrides: &Overrides,
69) {
70 match action {
71 Action::KeyCode(kc) => {
72 add_kc_output(osc_slot, kc.into(), outputs, overrides);
73 }
74 Action::HoldTap(HoldTapAction {
75 tap,
76 hold,
77 timeout_action,
78 ..
79 }) => {
80 add_key_output_from_action_to_key_pos(osc_slot, tap, outputs, overrides);
81 add_key_output_from_action_to_key_pos(osc_slot, hold, outputs, overrides);
82 add_key_output_from_action_to_key_pos(osc_slot, timeout_action, outputs, overrides);
83 }
84 Action::OneShot(OneShot { action: ac, .. }) => {
85 add_key_output_from_action_to_key_pos(osc_slot, ac, outputs, overrides);
86 }
87 Action::MultipleKeyCodes(kcs) => {
88 for kc in kcs.iter() {
89 add_kc_output(osc_slot, kc.into(), outputs, overrides);
90 }
91 }
92 Action::MultipleActions(actions) => {
93 for ac in actions.iter() {
94 add_key_output_from_action_to_key_pos(osc_slot, ac, outputs, overrides);
95 }
96 }
97 Action::TapDance(TapDance { actions, .. }) => {
98 for ac in actions.iter() {
99 add_key_output_from_action_to_key_pos(osc_slot, ac, outputs, overrides);
100 }
101 }
102 Action::Fork(ForkConfig { left, right, .. }) => {
103 add_key_output_from_action_to_key_pos(osc_slot, left, outputs, overrides);
104 add_key_output_from_action_to_key_pos(osc_slot, right, outputs, overrides);
105 }
106 Action::Chords(ChordsGroup { chords, .. }) => {
107 for (_, ac) in chords.iter() {
108 add_key_output_from_action_to_key_pos(osc_slot, ac, outputs, overrides);
109 }
110 }
111 Action::Switch(Switch { cases }) => {
112 for case in cases.iter() {
113 add_key_output_from_action_to_key_pos(osc_slot, case.1, outputs, overrides);
114 }
115 }
116 Action::Custom(cacs) => {
117 for ac in cacs.iter() {
118 match ac {
119 CustomAction::Unmodded { keys, .. } | CustomAction::Unshifted { keys } => {
120 for k in keys.iter() {
121 add_kc_output(osc_slot, k.into(), outputs, overrides);
122 }
123 }
124 _ => {}
125 }
126 }
127 }
128 Action::Src => {
129 add_kc_output(osc_slot, osc_slot, outputs, overrides);
130 }
131 Action::NoOp
132 | Action::Trans
133 | Action::Repeat
134 | Action::Layer(_)
135 | Action::DefaultLayer(_)
136 | Action::Sequence { .. }
137 | Action::RepeatableSequence { .. }
138 | Action::CancelSequences
139 | Action::OneShotIgnoreEventsTicks(_)
140 | Action::ReleaseState(_) => {}
141 };
142}
143
144pub(crate) fn add_kc_output(
145 osc_slot: OsCode,
146 osc: OsCode,
147 outs: &mut HashMap<OsCode, Vec<OsCode>>,
148 overrides: &Overrides,
149) {
150 let outputs = match outs.entry(osc_slot) {
151 Entry::Occupied(o) => o.into_mut(),
152 Entry::Vacant(v) => v.insert(vec![]),
153 };
154 if !outputs.contains(&osc) {
155 outputs.push(osc);
156 }
157 for ov_osc in overrides
158 .output_non_mods_for_input_non_mod(osc)
159 .iter()
160 .copied()
161 {
162 if !outputs.contains(&ov_osc) {
163 outputs.push(ov_osc);
164 }
165 }
166}