Skip to content

Commit 0bb5b4c

Browse files
committed
Gamepad / Keyboard / Mouse: adds support to ignore input devices by name prefix
Fixes #1950
1 parent 1180eb5 commit 0bb5b4c

File tree

7 files changed

+238
-5
lines changed

7 files changed

+238
-5
lines changed

doc/json_schema.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2636,6 +2636,15 @@
26362636
"const": "gamepad",
26372637
"description": "List connected gamepads"
26382638
},
2639+
"ignores": {
2640+
"type": "array",
2641+
"description": "An array of case-insensitive device name prefixes to ignore",
2642+
"items": {
2643+
"type": "string"
2644+
},
2645+
"minItems": 1,
2646+
"uniqueItems": true
2647+
},
26392648
"percent": {
26402649
"$ref": "#/$defs/percent"
26412650
},
@@ -2895,6 +2904,15 @@
28952904
"const": "keyboard",
28962905
"description": "List (connected) keyboards"
28972906
},
2907+
"ignores": {
2908+
"type": "array",
2909+
"description": "An array of case-insensitive device name prefixes to ignore",
2910+
"items": {
2911+
"type": "string"
2912+
},
2913+
"minItems": 1,
2914+
"uniqueItems": true
2915+
},
28982916
"key": {
28992917
"$ref": "#/$defs/key"
29002918
},
@@ -3218,6 +3236,15 @@
32183236
"const": "mouse",
32193237
"description": "List connected mouses"
32203238
},
3239+
"ignores": {
3240+
"type": "array",
3241+
"description": "An array of case-insensitive device name prefixes to ignore",
3242+
"items": {
3243+
"type": "string"
3244+
},
3245+
"minItems": 1,
3246+
"uniqueItems": true
3247+
},
32213248
"key": {
32223249
"$ref": "#/$defs/key"
32233250
},

src/modules/gamepad/gamepad.c

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,40 @@ bool ffPrintGamepad(FFGamepadOptions* options)
6868
return false;
6969
}
7070

71+
FF_LIST_AUTO_DESTROY filtered = ffListCreate(sizeof(FFGamepadDevice*));
72+
FF_LIST_FOR_EACH(FFGamepadDevice, device, result)
73+
{
74+
bool ignored = false;
75+
FF_LIST_FOR_EACH(FFstrbuf, ignore, options->ignores)
76+
{
77+
if(ffStrbufStartsWithIgnCase(&device->name, ignore))
78+
{
79+
ignored = true;
80+
break;
81+
}
82+
}
83+
if(!ignored)
84+
{
85+
FFGamepadDevice** ptr = ffListAdd(&filtered);
86+
*ptr = device;
87+
}
88+
}
89+
90+
if(!filtered.length)
91+
{
92+
ffPrintError(FF_GAMEPAD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored");
93+
return false;
94+
}
95+
7196
uint8_t index = 0;
97+
FF_LIST_FOR_EACH(FFGamepadDevice*, pdevice, filtered)
98+
{
99+
FFGamepadDevice* device = *pdevice;
100+
printDevice(options, device, filtered.length > 1 ? ++index : 0);
101+
}
102+
72103
FF_LIST_FOR_EACH(FFGamepadDevice, device, result)
73104
{
74-
printDevice(options, device, result.length > 1 ? ++index : 0);
75105
ffStrbufDestroy(&device->serial);
76106
ffStrbufDestroy(&device->name);
77107
}
@@ -88,6 +118,21 @@ void ffParseGamepadJsonObject(FFGamepadOptions* options, yyjson_val* module)
88118
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
89119
continue;
90120

121+
if (unsafe_yyjson_equals_str(key, "ignores"))
122+
{
123+
yyjson_val *elem;
124+
size_t eidx, emax;
125+
yyjson_arr_foreach(val, eidx, emax, elem)
126+
{
127+
if (yyjson_is_str(elem))
128+
{
129+
FFstrbuf* strbuf = ffListAdd(&options->ignores);
130+
ffStrbufInitJsonVal(strbuf, elem);
131+
}
132+
}
133+
continue;
134+
}
135+
91136
if (ffPercentParseJsonObject(key, val, &options->percent))
92137
continue;
93138

@@ -99,6 +144,12 @@ void ffGenerateGamepadJsonConfig(FFGamepadOptions* options, yyjson_mut_doc* doc,
99144
{
100145
ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs);
101146

147+
if (options->ignores.length > 0)
148+
{
149+
yyjson_mut_val* ignores = yyjson_mut_obj_add_arr(doc, module, "ignores");
150+
FF_LIST_FOR_EACH(FFstrbuf, strbuf, options->ignores)
151+
yyjson_mut_arr_append(ignores, yyjson_mut_strncpy(doc, strbuf->chars, strbuf->length));
152+
}
102153
ffPercentGenerateJsonConfig(doc, module, options->percent);
103154
}
104155

@@ -120,6 +171,17 @@ bool ffGenerateGamepadJsonResult(FF_MAYBE_UNUSED FFGamepadOptions* options, yyjs
120171
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
121172
yyjson_mut_obj_add_strbuf(doc, obj, "serial", &device->serial);
122173
yyjson_mut_obj_add_strbuf(doc, obj, "name", &device->name);
174+
175+
bool ignored = false;
176+
FF_LIST_FOR_EACH(FFstrbuf, ignore, options->ignores)
177+
{
178+
if(ffStrbufStartsWithIgnCase(&device->name, ignore))
179+
{
180+
ignored = true;
181+
break;
182+
}
183+
}
184+
yyjson_mut_obj_add_bool(doc, obj, "ignored", ignored);
123185
}
124186

125187
FF_LIST_FOR_EACH(FFGamepadDevice, device, result)
@@ -134,12 +196,18 @@ bool ffGenerateGamepadJsonResult(FF_MAYBE_UNUSED FFGamepadOptions* options, yyjs
134196
void ffInitGamepadOptions(FFGamepadOptions* options)
135197
{
136198
ffOptionInitModuleArg(&options->moduleArgs, "󰺵");
199+
200+
ffListInit(&options->ignores, sizeof(FFstrbuf));
137201
options->percent = (FFPercentageModuleConfig) { 50, 20, 0 };
138202
}
139203

140204
void ffDestroyGamepadOptions(FFGamepadOptions* options)
141205
{
142206
ffOptionDestroyModuleArg(&options->moduleArgs);
207+
208+
FF_LIST_FOR_EACH(FFstrbuf, str, options->ignores)
209+
ffStrbufDestroy(str);
210+
ffListDestroy(&options->ignores);
143211
}
144212

145213
FFModuleBaseInfo ffGamepadModuleInfo = {

src/modules/gamepad/option.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
#pragma once
22

33
#include "common/option.h"
4+
#include "util/FFlist.h"
45

56
typedef struct FFGamepadOptions
67
{
78
FFModuleArgs moduleArgs;
89

10+
FFlist ignores; // List of FFstrbuf
911
FFPercentageModuleConfig percent;
1012
} FFGamepadOptions;
1113

src/modules/keyboard/keyboard.c

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,36 @@ bool ffPrintKeyboard(FFKeyboardOptions* options)
3939
return false;
4040
}
4141

42-
uint8_t index = 0;
42+
FF_LIST_AUTO_DESTROY filtered = ffListCreate(sizeof(FFKeyboardDevice*));
4343
FF_LIST_FOR_EACH(FFKeyboardDevice, device, result)
4444
{
45-
printDevice(options, device, result.length > 1 ? ++index : 0);
45+
bool ignored = false;
46+
FF_LIST_FOR_EACH(FFstrbuf, ignore, options->ignores)
47+
{
48+
if(ffStrbufStartsWithIgnCase(&device->name, ignore))
49+
{
50+
ignored = true;
51+
break;
52+
}
53+
}
54+
if(!ignored)
55+
{
56+
FFKeyboardDevice** ptr = ffListAdd(&filtered);
57+
*ptr = device;
58+
}
59+
}
60+
61+
if(!filtered.length)
62+
{
63+
ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored");
64+
return false;
65+
}
66+
67+
uint8_t index = 0;
68+
FF_LIST_FOR_EACH(FFKeyboardDevice*, pdevice, filtered)
69+
{
70+
FFKeyboardDevice* device = *pdevice;
71+
printDevice(options, device, filtered.length > 1 ? ++index : 0);
4672
ffStrbufDestroy(&device->serial);
4773
ffStrbufDestroy(&device->name);
4874
}
@@ -59,13 +85,35 @@ void ffParseKeyboardJsonObject(FFKeyboardOptions* options, yyjson_val* module)
5985
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
6086
continue;
6187

88+
if (unsafe_yyjson_equals_str(key, "ignores"))
89+
{
90+
yyjson_val *elem;
91+
size_t eidx, emax;
92+
yyjson_arr_foreach(val, eidx, emax, elem)
93+
{
94+
if (yyjson_is_str(elem))
95+
{
96+
FFstrbuf* strbuf = ffListAdd(&options->ignores);
97+
ffStrbufInitJsonVal(strbuf, elem);
98+
}
99+
}
100+
continue;
101+
}
102+
62103
ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
63104
}
64105
}
65106

66107
void ffGenerateKeyboardJsonConfig(FFKeyboardOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
67108
{
68109
ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs);
110+
111+
if (options->ignores.length > 0)
112+
{
113+
yyjson_mut_val* ignores = yyjson_mut_obj_add_arr(doc, module, "ignores");
114+
FF_LIST_FOR_EACH(FFstrbuf, strbuf, options->ignores)
115+
yyjson_mut_arr_append(ignores, yyjson_mut_strncpy(doc, strbuf->chars, strbuf->length));
116+
}
69117
}
70118

71119
bool ffGenerateKeyboardJsonResult(FF_MAYBE_UNUSED FFKeyboardOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
@@ -86,6 +134,17 @@ bool ffGenerateKeyboardJsonResult(FF_MAYBE_UNUSED FFKeyboardOptions* options, yy
86134
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
87135
yyjson_mut_obj_add_strbuf(doc, obj, "serial", &device->serial);
88136
yyjson_mut_obj_add_strbuf(doc, obj, "name", &device->name);
137+
138+
bool ignored = false;
139+
FF_LIST_FOR_EACH(FFstrbuf, ignore, options->ignores)
140+
{
141+
if(ffStrbufStartsWithIgnCase(&device->name, ignore))
142+
{
143+
ignored = true;
144+
break;
145+
}
146+
}
147+
yyjson_mut_obj_add_bool(doc, obj, "ignored", ignored);
89148
}
90149

91150
FF_LIST_FOR_EACH(FFKeyboardDevice, device, result)
@@ -100,11 +159,17 @@ bool ffGenerateKeyboardJsonResult(FF_MAYBE_UNUSED FFKeyboardOptions* options, yy
100159
void ffInitKeyboardOptions(FFKeyboardOptions* options)
101160
{
102161
ffOptionInitModuleArg(&options->moduleArgs, "");
162+
163+
ffListInit(&options->ignores, sizeof(FFstrbuf));
103164
}
104165

105166
void ffDestroyKeyboardOptions(FFKeyboardOptions* options)
106167
{
107168
ffOptionDestroyModuleArg(&options->moduleArgs);
169+
170+
FF_LIST_FOR_EACH(FFstrbuf, str, options->ignores)
171+
ffStrbufDestroy(str);
172+
ffListDestroy(&options->ignores);
108173
}
109174

110175
FFModuleBaseInfo ffKeyboardModuleInfo = {

src/modules/keyboard/option.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
#pragma once
22

33
#include "common/option.h"
4+
#include "util/FFlist.h"
45

56
typedef struct FFKeyboardOptions
67
{
78
FFModuleArgs moduleArgs;
9+
10+
FFlist ignores; // List of FFstrbuf
811
} FFKeyboardOptions;
912

1013
static_assert(sizeof(FFKeyboardOptions) <= FF_OPTION_MAX_SIZE, "FFKeyboardOptions size exceeds maximum allowed size");

0 commit comments

Comments
 (0)