diff --git a/CMakeLists.txt b/CMakeLists.txt index b30be6d45..77f717f13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -379,6 +379,7 @@ set(LIBFASTFETCH_SRC src/modules/initsystem/initsystem.c src/modules/gamepad/gamepad.c src/modules/kernel/kernel.c + src/modules/keyboard/keyboard.c src/modules/lm/lm.c src/modules/loadavg/loadavg.c src/modules/locale/locale.c @@ -402,6 +403,7 @@ set(LIBFASTFETCH_SRC src/modules/sound/sound.c src/modules/swap/swap.c src/modules/media/media.c + src/modules/mouse/mouse.c src/modules/terminal/terminal.c src/modules/terminaltheme/terminaltheme.c src/modules/terminalfont/terminalfont.c @@ -478,6 +480,7 @@ if(LINUX) src/detection/host/host_linux.c src/detection/icons/icons_linux.c src/detection/initsystem/initsystem_linux.c + src/detection/keyboard/keyboard_linux.c src/detection/libc/libc_linux.c src/detection/lm/lm_linux.c src/detection/loadavg/loadavg_linux.c @@ -486,6 +489,7 @@ if(LINUX) src/detection/gamepad/gamepad_linux.c src/detection/media/media_linux.c src/detection/memory/memory_linux.c + src/detection/mouse/mouse_linux.c src/detection/netio/netio_linux.c src/detection/opengl/opengl_linux.c src/detection/os/os_linux.c @@ -542,6 +546,7 @@ elseif(ANDROID) src/detection/host/host_android.c src/detection/icons/icons_nosupport.c src/detection/initsystem/initsystem_linux.c + src/detection/keyboard/keyboard_nosupport.c src/detection/libc/libc_android.c src/detection/lm/lm_nosupport.c src/detection/loadavg/loadavg_linux.c @@ -550,6 +555,7 @@ elseif(ANDROID) src/detection/gamepad/gamepad_nosupport.c src/detection/media/media_nosupport.c src/detection/memory/memory_linux.c + src/detection/mouse/mouse_nosupport.c src/detection/netio/netio_linux.c src/detection/opengl/opengl_linux.c src/detection/os/os_android.c @@ -622,6 +628,7 @@ elseif(FreeBSD) src/detection/lm/lm_linux.c src/detection/icons/icons_linux.c src/detection/initsystem/initsystem_linux.c + src/detection/keyboard/keyboard_nosupport.c src/detection/libc/libc_bsd.c src/detection/loadavg/loadavg_bsd.c src/detection/locale/locale_linux.c @@ -629,6 +636,7 @@ elseif(FreeBSD) src/detection/gamepad/gamepad_bsd.c src/detection/media/media_linux.c src/detection/memory/memory_bsd.c + src/detection/mouse/mouse_nosupport.c src/detection/netio/netio_bsd.c src/detection/opengl/opengl_linux.c src/detection/os/os_linux.c @@ -701,6 +709,7 @@ elseif(OpenBSD) src/detection/lm/lm_nosupport.c src/detection/icons/icons_linux.c src/detection/initsystem/initsystem_linux.c + src/detection/keyboard/keyboard_nosupport.c src/detection/libc/libc_nosupport.c src/detection/loadavg/loadavg_bsd.c src/detection/locale/locale_linux.c @@ -708,6 +717,7 @@ elseif(OpenBSD) src/detection/gamepad/gamepad_nosupport.c src/detection/media/media_linux.c src/detection/memory/memory_obsd.c + src/detection/mouse/mouse_nosupport.c src/detection/netio/netio_nosupport.c src/detection/opengl/opengl_linux.c src/detection/os/os_obsd.c @@ -766,6 +776,7 @@ elseif(APPLE) src/detection/host/host_apple.c src/detection/icons/icons_nosupport.c src/detection/initsystem/initsystem_linux.c + src/detection/keyboard/keyboard_apple.c src/detection/lm/lm_nosupport.c src/detection/loadavg/loadavg_bsd.c src/detection/libc/libc_apple.c @@ -774,6 +785,7 @@ elseif(APPLE) src/detection/gamepad/gamepad_apple.c src/detection/media/media_apple.m src/detection/memory/memory_apple.c + src/detection/mouse/mouse_apple.c src/detection/netio/netio_bsd.c src/detection/opengl/opengl_apple.c src/detection/os/os_apple.m @@ -832,6 +844,7 @@ elseif(WIN32) src/detection/host/host_windows.c src/detection/icons/icons_windows.c src/detection/initsystem/initsystem_nosupport.c + src/detection/keyboard/keyboard_windows.c src/detection/libc/libc_windows.cpp src/detection/lm/lm_nosupport.c src/detection/loadavg/loadavg_nosupport.c @@ -840,6 +853,7 @@ elseif(WIN32) src/detection/gamepad/gamepad_windows.c src/detection/media/media_windows.c src/detection/memory/memory_windows.c + src/detection/mouse/mouse_windows.c src/detection/physicalmemory/physicalmemory_linux.c src/detection/netio/netio_windows.c src/detection/opengl/opengl_windows.c @@ -1027,7 +1041,7 @@ if(FreeBSD AND EXISTS "/usr/local/bin/objdump") endif() if(LINUX OR ANDROID) - target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__=1 _FILE_OFFSET_BITS=64) + target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE _ATFILE_SOURCE __STDC_WANT_LIB_EXT1__ _FILE_OFFSET_BITS=64) elseif(WIN32) target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE WIN32_LEAN_AND_MEAN=1 _WIN32_WINNT=0x0A00) elseif(APPLE) diff --git a/src/common/modules.c b/src/common/modules.c index 4e8ae69e4..ce649cfc9 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -73,6 +73,7 @@ static FFModuleBaseInfo* J[] = { static FFModuleBaseInfo* K[] = { (void*) &instance.config.modules.kernel, + (void*) &instance.config.modules.keyboard, NULL, }; @@ -88,6 +89,7 @@ static FFModuleBaseInfo* M[] = { (void*) &instance.config.modules.media, (void*) &instance.config.modules.memory, (void*) &instance.config.modules.monitor, + (void*) &instance.config.modules.mouse, NULL, }; diff --git a/src/detection/gamepad/gamepad_linux.c b/src/detection/gamepad/gamepad_linux.c index 50d04df5e..808628934 100644 --- a/src/detection/gamepad/gamepad_linux.c +++ b/src/detection/gamepad/gamepad_linux.c @@ -68,7 +68,7 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */) { if (!ffStrStartsWith(entry->d_name, "js")) continue; - if (!ffCharIsDigit(entry->d_name[2])) + if (!ffCharIsDigit(entry->d_name[strlen("js")])) continue; ffStrbufAppendS(&path, entry->d_name); diff --git a/src/detection/keyboard/keyboard.h b/src/detection/keyboard/keyboard.h new file mode 100644 index 000000000..8f0a8a85e --- /dev/null +++ b/src/detection/keyboard/keyboard.h @@ -0,0 +1,9 @@ +#include "fastfetch.h" + +typedef struct FFKeyboardDevice +{ + FFstrbuf serial; + FFstrbuf name; +} FFKeyboardDevice; + +const char* ffDetectKeyboard(FFlist* devices /* List of FFKeyboardDevice */); diff --git a/src/detection/keyboard/keyboard_apple.c b/src/detection/keyboard/keyboard_apple.c new file mode 100644 index 000000000..f0d4def0c --- /dev/null +++ b/src/detection/keyboard/keyboard_apple.c @@ -0,0 +1,54 @@ +#include "keyboard.h" +#include "util/apple/cf_helpers.h" +#include "util/mallocHelper.h" + +#include +#include + +static void enumSet(IOHIDDeviceRef value, FFlist* results) +{ + FFKeyboardDevice* device = (FFKeyboardDevice*) ffListAdd(results); + ffStrbufInit(&device->serial); + ffStrbufInit(&device->name); + + CFStringRef manufacturer = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDManufacturerKey)); + ffCfStrGetString(manufacturer, &device->name); + + CFStringRef product = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDProductKey)); + if (device->name.length) + { + ffCfStrGetString(product, &device->serial); + ffStrbufAppendC(&device->name, ' '); + ffStrbufAppend(&device->name, &device->serial); + } + else + { + ffCfStrGetString(product, &device->name); + } + + CFStringRef serialNumber = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDSerialNumberKey)); + ffCfStrGetString(serialNumber, &device->serial); +} + +const char* ffDetectKeyboard(FFlist* devices /* List of FFKeyboardDevice */) +{ + IOHIDManagerRef FF_CFTYPE_AUTO_RELEASE manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + if (IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone) != kIOReturnSuccess) + return "IOHIDManagerOpen() failed"; + + CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching1 = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){ + CFSTR(kIOHIDDeviceUsagePageKey), + CFSTR(kIOHIDDeviceUsageKey) + }, (const void **)(CFNumberRef[]){ + ffCfCreateInt(kHIDPage_GenericDesktop), + ffCfCreateInt(kHIDUsage_GD_Keyboard) + }, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + IOHIDManagerSetDeviceMatching(manager, matching1); + + CFSetRef FF_CFTYPE_AUTO_RELEASE set = IOHIDManagerCopyDevices(manager); + if (set) + CFSetApplyFunction(set, (CFSetApplierFunction) &enumSet, devices); + IOHIDManagerClose(manager, kIOHIDOptionsTypeNone); + + return NULL; +} diff --git a/src/detection/keyboard/keyboard_linux.c b/src/detection/keyboard/keyboard_linux.c new file mode 100644 index 000000000..42618272f --- /dev/null +++ b/src/detection/keyboard/keyboard_linux.c @@ -0,0 +1,57 @@ +#include "keyboard.h" +#include "common/io/io.h" +#include "util/stringUtils.h" + +const char* ffDetectKeyboard(FFlist* devices /* List of FFKeyboardDevice */) +{ + // There is no /sys/class/input/kbd* on Linux + FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/dev/input/by-path/"); + if (dirp == NULL) + return "opendir(\"/dev/input/by-path/\") == NULL"; + + uint64_t flags = 0; + + FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate(); + + struct dirent* entry; + while ((entry = readdir(dirp)) != NULL) + { + if (!ffStrEndsWith(entry->d_name, "-event-kbd")) + continue; + + char buffer[32]; // `../eventX` + ssize_t len = readlinkat(dirfd(dirp), entry->d_name, buffer, sizeof(buffer) - 1); + if (len != strlen("../eventX") || !ffStrStartsWith(buffer, "../event")) continue; + buffer[len] = 0; + + const char* eventid = buffer + strlen("../event"); + + char* pend = NULL; + uint32_t index = (uint32_t) strtoul(eventid, &pend, 10); + if (pend == eventid) continue; + + // Ignore duplicate entries + if (flags & (1 << index)) + continue; + flags |= (1 << index); + + ffStrbufSetF(&path, "/sys/class/input/event%s/device/name", eventid); + + FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); + if (ffAppendFileBuffer(path.chars, &name)) + { + ffStrbufTrimRightSpace(&name); + ffStrbufSubstrBefore(&path, path.length - 4); + + FFKeyboardDevice* device = (FFKeyboardDevice*) ffListAdd(devices); + ffStrbufInitMove(&device->name, &name); + ffStrbufInit(&device->serial); + + ffStrbufAppendS(&path, "uniq"); + if (ffAppendFileBuffer(path.chars, &device->serial)) + ffStrbufTrimRightSpace(&device->serial); + } + } + + return NULL; +} diff --git a/src/detection/mouse/mouse.h b/src/detection/mouse/mouse.h new file mode 100644 index 000000000..710b4f8df --- /dev/null +++ b/src/detection/mouse/mouse.h @@ -0,0 +1,9 @@ +#include "fastfetch.h" + +typedef struct FFMouseDevice +{ + FFstrbuf serial; + FFstrbuf name; +} FFMouseDevice; + +const char* ffDetectMouse(FFlist* devices /* List of FFMouseDevice */); diff --git a/src/detection/mouse/mouse_apple.c b/src/detection/mouse/mouse_apple.c new file mode 100644 index 000000000..511b0ff56 --- /dev/null +++ b/src/detection/mouse/mouse_apple.c @@ -0,0 +1,54 @@ +#include "mouse.h" +#include "util/apple/cf_helpers.h" +#include "util/mallocHelper.h" + +#include +#include + +static void enumSet(IOHIDDeviceRef value, FFlist* results) +{ + FFMouseDevice* device = (FFMouseDevice*) ffListAdd(results); + ffStrbufInit(&device->serial); + ffStrbufInit(&device->name); + + CFStringRef manufacturer = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDManufacturerKey)); + ffCfStrGetString(manufacturer, &device->name); + + CFStringRef product = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDProductKey)); + if (device->name.length) + { + ffCfStrGetString(product, &device->serial); + ffStrbufAppendC(&device->name, ' '); + ffStrbufAppend(&device->name, &device->serial); + } + else + { + ffCfStrGetString(product, &device->name); + } + + CFStringRef serialNumber = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDSerialNumberKey)); + ffCfStrGetString(serialNumber, &device->serial); +} + +const char* ffDetectMouse(FFlist* devices /* List of FFMouseDevice */) +{ + IOHIDManagerRef FF_CFTYPE_AUTO_RELEASE manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + if (IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone) != kIOReturnSuccess) + return "IOHIDManagerOpen() failed"; + + CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching1 = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){ + CFSTR(kIOHIDDeviceUsagePageKey), + CFSTR(kIOHIDDeviceUsageKey) + }, (const void **)(CFNumberRef[]){ + ffCfCreateInt(kHIDPage_GenericDesktop), + ffCfCreateInt(kHIDUsage_GD_Mouse) + }, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + IOHIDManagerSetDeviceMatching(manager, matching1); + + CFSetRef FF_CFTYPE_AUTO_RELEASE set = IOHIDManagerCopyDevices(manager); + if (set) + CFSetApplyFunction(set, (CFSetApplierFunction) &enumSet, devices); + IOHIDManagerClose(manager, kIOHIDOptionsTypeNone); + + return NULL; +} diff --git a/src/detection/mouse/mouse_linux.c b/src/detection/mouse/mouse_linux.c new file mode 100644 index 000000000..d03a3e7e5 --- /dev/null +++ b/src/detection/mouse/mouse_linux.c @@ -0,0 +1,44 @@ +#include "mouse.h" +#include "common/io/io.h" +#include "util/stringUtils.h" + +const char* ffDetectMouse(FFlist* devices /* List of FFMouseDevice */) +{ + FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/input/"); + if (dirp == NULL) + return "opendir(\"/sys/class/input/\") == NULL"; + + FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/sys/class/input/"); + uint32_t baseLen = path.length; + + struct dirent* entry; + while ((entry = readdir(dirp)) != NULL) + { + if (!ffStrStartsWith(entry->d_name, "mouse")) + continue; + if (!ffCharIsDigit(entry->d_name[strlen("mouse")])) + continue; + + ffStrbufAppendS(&path, entry->d_name); + ffStrbufAppendS(&path, "/device/name"); + + FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); + if (ffAppendFileBuffer(path.chars, &name)) + { + ffStrbufTrimRightSpace(&name); + ffStrbufSubstrBefore(&path, path.length - 4); + + FFMouseDevice* device = (FFMouseDevice*) ffListAdd(devices); + ffStrbufInitMove(&device->name, &name); + ffStrbufInit(&device->serial); + + ffStrbufAppendS(&path, "uniq"); + if (ffAppendFileBuffer(path.chars, &device->serial)) + ffStrbufTrimRightSpace(&device->serial); + } + + ffStrbufSubstrBefore(&path, baseLen); + } + + return NULL; +} diff --git a/src/modules/keyboard/keyboard.c b/src/modules/keyboard/keyboard.c new file mode 100644 index 000000000..fcf5eba8b --- /dev/null +++ b/src/modules/keyboard/keyboard.c @@ -0,0 +1,142 @@ +#include "common/percent.h" +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "detection/keyboard/keyboard.h" +#include "modules/keyboard/keyboard.h" +#include "util/stringUtils.h" + +#define FF_KEYBOARD_NUM_FORMAT_ARGS 2 + +static void printDevice(FFKeyboardOptions* options, const FFKeyboardDevice* device, uint8_t index) +{ + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(FF_KEYBOARD_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffStrbufPutTo(&device->name, stdout); + } + else + { + FF_PRINT_FORMAT_CHECKED(FF_KEYBOARD_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_KEYBOARD_NUM_FORMAT_ARGS, ((FFformatarg[]) { + FF_FORMAT_ARG(device->name, "name"), + FF_FORMAT_ARG(device->serial, "serial"), + })); + } +} + +void ffPrintKeyboard(FFKeyboardOptions* options) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFKeyboardDevice)); + + const char* error = ffDetectKeyboard(&result); + + if(error) + { + ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + return; + } + + if(!result.length) + { + ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); + return; + } + + uint8_t index = 0; + FF_LIST_FOR_EACH(FFKeyboardDevice, device, result) + { + printDevice(options, device, result.length > 1 ? ++index : 0); + ffStrbufDestroy(&device->serial); + ffStrbufDestroy(&device->name); + } +} + +bool ffParseKeyboardCommandOptions(FFKeyboardOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_KEYBOARD_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + return false; +} + +void ffParseKeyboardJsonObject(FFKeyboardOptions* options, yyjson_val* module) +{ + yyjson_val *key_, *val; + size_t idx, max; + yyjson_obj_foreach(module, idx, max, key_, val) + { + const char* key = yyjson_get_str(key_); + if(ffStrEqualsIgnCase(key, "type")) + continue; + + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) + continue; + + ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + } +} + +void ffGenerateKeyboardJsonConfig(FFKeyboardOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + __attribute__((__cleanup__(ffDestroyKeyboardOptions))) FFKeyboardOptions defaultOptions; + ffInitKeyboardOptions(&defaultOptions); + + ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); +} + +void ffGenerateKeyboardJsonResult(FF_MAYBE_UNUSED FFKeyboardOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFKeyboardDevice)); + + const char* error = ffDetectKeyboard(&result); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(FFKeyboardDevice, device, result) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_strbuf(doc, obj, "serial", &device->serial); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &device->name); + } + + FF_LIST_FOR_EACH(FFKeyboardDevice, device, result) + { + ffStrbufDestroy(&device->serial); + ffStrbufDestroy(&device->name); + } +} + +void ffPrintKeyboardHelpFormat(void) +{ + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_KEYBOARD_MODULE_NAME, "{1} ({3})", FF_KEYBOARD_NUM_FORMAT_ARGS, ((const char* []) { + "Name - name", + "Serial number - serial", + })); +} + +void ffInitKeyboardOptions(FFKeyboardOptions* options) +{ + ffOptionInitModuleBaseInfo( + &options->moduleInfo, + FF_KEYBOARD_MODULE_NAME, + "List connected keyboards", + ffParseKeyboardCommandOptions, + ffParseKeyboardJsonObject, + ffPrintKeyboard, + ffGenerateKeyboardJsonResult, + ffPrintKeyboardHelpFormat, + ffGenerateKeyboardJsonConfig + ); + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyKeyboardOptions(FFKeyboardOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} diff --git a/src/modules/keyboard/keyboard.h b/src/modules/keyboard/keyboard.h new file mode 100644 index 000000000..b54a3ccba --- /dev/null +++ b/src/modules/keyboard/keyboard.h @@ -0,0 +1,9 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_KEYBOARD_MODULE_NAME "Keyboard" + +void ffPrintKeyboard(FFKeyboardOptions* options); +void ffInitKeyboardOptions(FFKeyboardOptions* options); +void ffDestroyKeyboardOptions(FFKeyboardOptions* options); diff --git a/src/modules/keyboard/option.h b/src/modules/keyboard/option.h new file mode 100644 index 000000000..4f39eee19 --- /dev/null +++ b/src/modules/keyboard/option.h @@ -0,0 +1,11 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef struct FFKeyboardOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; +} FFKeyboardOptions; diff --git a/src/modules/modules.h b/src/modules/modules.h index 4f9fa7a40..e6594f030 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -34,6 +34,7 @@ #include "modules/icons/icons.h" #include "modules/initsystem/initsystem.h" #include "modules/kernel/kernel.h" +#include "modules/keyboard/keyboard.h" #include "modules/lm/lm.h" #include "modules/loadavg/loadavg.h" #include "modules/locale/locale.h" @@ -41,6 +42,7 @@ #include "modules/media/media.h" #include "modules/memory/memory.h" #include "modules/monitor/monitor.h" +#include "modules/mouse/mouse.h" #include "modules/netio/netio.h" #include "modules/opengl/opengl.h" #include "modules/opencl/opencl.h" diff --git a/src/modules/mouse/mouse.c b/src/modules/mouse/mouse.c new file mode 100644 index 000000000..27b749f47 --- /dev/null +++ b/src/modules/mouse/mouse.c @@ -0,0 +1,142 @@ +#include "common/percent.h" +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "detection/mouse/mouse.h" +#include "modules/mouse/mouse.h" +#include "util/stringUtils.h" + +#define FF_MOUSE_NUM_FORMAT_ARGS 2 + +static void printDevice(FFMouseOptions* options, const FFMouseDevice* device, uint8_t index) +{ + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(FF_MOUSE_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffStrbufPutTo(&device->name, stdout); + } + else + { + FF_PRINT_FORMAT_CHECKED(FF_MOUSE_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_MOUSE_NUM_FORMAT_ARGS, ((FFformatarg[]) { + FF_FORMAT_ARG(device->name, "name"), + FF_FORMAT_ARG(device->serial, "serial"), + })); + } +} + +void ffPrintMouse(FFMouseOptions* options) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFMouseDevice)); + + const char* error = ffDetectMouse(&result); + + if(error) + { + ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + return; + } + + if(!result.length) + { + ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); + return; + } + + uint8_t index = 0; + FF_LIST_FOR_EACH(FFMouseDevice, device, result) + { + printDevice(options, device, result.length > 1 ? ++index : 0); + ffStrbufDestroy(&device->serial); + ffStrbufDestroy(&device->name); + } +} + +bool ffParseMouseCommandOptions(FFMouseOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_MOUSE_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + return false; +} + +void ffParseMouseJsonObject(FFMouseOptions* options, yyjson_val* module) +{ + yyjson_val *key_, *val; + size_t idx, max; + yyjson_obj_foreach(module, idx, max, key_, val) + { + const char* key = yyjson_get_str(key_); + if(ffStrEqualsIgnCase(key, "type")) + continue; + + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) + continue; + + ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + } +} + +void ffGenerateMouseJsonConfig(FFMouseOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + __attribute__((__cleanup__(ffDestroyMouseOptions))) FFMouseOptions defaultOptions; + ffInitMouseOptions(&defaultOptions); + + ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); +} + +void ffGenerateMouseJsonResult(FF_MAYBE_UNUSED FFMouseOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFMouseDevice)); + + const char* error = ffDetectMouse(&result); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(FFMouseDevice, device, result) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_strbuf(doc, obj, "serial", &device->serial); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &device->name); + } + + FF_LIST_FOR_EACH(FFMouseDevice, device, result) + { + ffStrbufDestroy(&device->serial); + ffStrbufDestroy(&device->name); + } +} + +void ffPrintMouseHelpFormat(void) +{ + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_MOUSE_MODULE_NAME, "{1} ({3})", FF_MOUSE_NUM_FORMAT_ARGS, ((const char* []) { + "Name - name", + "Serial number - serial", + })); +} + +void ffInitMouseOptions(FFMouseOptions* options) +{ + ffOptionInitModuleBaseInfo( + &options->moduleInfo, + FF_MOUSE_MODULE_NAME, + "List connected mouses", + ffParseMouseCommandOptions, + ffParseMouseJsonObject, + ffPrintMouse, + ffGenerateMouseJsonResult, + ffPrintMouseHelpFormat, + ffGenerateMouseJsonConfig + ); + ffOptionInitModuleArg(&options->moduleArgs, "󰍽"); +} + +void ffDestroyMouseOptions(FFMouseOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} diff --git a/src/modules/mouse/mouse.h b/src/modules/mouse/mouse.h new file mode 100644 index 000000000..d78a375ae --- /dev/null +++ b/src/modules/mouse/mouse.h @@ -0,0 +1,9 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_MOUSE_MODULE_NAME "Mouse" + +void ffPrintMouse(FFMouseOptions* options); +void ffInitMouseOptions(FFMouseOptions* options); +void ffDestroyMouseOptions(FFMouseOptions* options); diff --git a/src/modules/mouse/option.h b/src/modules/mouse/option.h new file mode 100644 index 000000000..db9ea1866 --- /dev/null +++ b/src/modules/mouse/option.h @@ -0,0 +1,11 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef struct FFMouseOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; +} FFMouseOptions; diff --git a/src/modules/options.h b/src/modules/options.h index 783757d3a..7cf98c127 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -34,6 +34,7 @@ #include "modules/icons/option.h" #include "modules/initsystem/option.h" #include "modules/kernel/option.h" +#include "modules/keyboard/option.h" #include "modules/loadavg/option.h" #include "modules/locale/option.h" #include "modules/lm/option.h" @@ -41,6 +42,7 @@ #include "modules/media/option.h" #include "modules/memory/option.h" #include "modules/monitor/option.h" +#include "modules/mouse/option.h" #include "modules/netio/option.h" #include "modules/opengl/option.h" #include "modules/opencl/option.h" diff --git a/src/options/modules.c b/src/options/modules.c index cea3c7af0..755f65a87 100644 --- a/src/options/modules.c +++ b/src/options/modules.c @@ -35,6 +35,7 @@ void ffOptionsInitModules(FFOptionsModules* options) ffInitIconsOptions(&options->icons); ffInitInitSystemOptions(&options->initSystem); ffInitKernelOptions(&options->kernel); + ffInitKeyboardOptions(&options->keyboard); ffInitLMOptions(&options->lm); ffInitLoadavgOptions(&options->loadavg); ffInitLocalIpOptions(&options->localIP); @@ -42,6 +43,7 @@ void ffOptionsInitModules(FFOptionsModules* options) ffInitMediaOptions(&options->media); ffInitMemoryOptions(&options->memory); ffInitMonitorOptions(&options->monitor); + ffInitMouseOptions(&options->mouse); ffInitNetIOOptions(&options->netIo); ffInitOSOptions(&options->os); ffInitOpenCLOptions(&options->openCL); @@ -110,6 +112,7 @@ void ffOptionsDestroyModules(FFOptionsModules* options) ffDestroyIconsOptions(&options->icons); ffDestroyInitSystemOptions(&options->initSystem); ffDestroyKernelOptions(&options->kernel); + ffDestroyKeyboardOptions(&options->keyboard); ffDestroyLMOptions(&options->lm); ffDestroyLoadavgOptions(&options->loadavg); ffDestroyLocalIpOptions(&options->localIP); @@ -117,6 +120,7 @@ void ffOptionsDestroyModules(FFOptionsModules* options) ffDestroyMediaOptions(&options->media); ffDestroyMemoryOptions(&options->memory); ffDestroyMonitorOptions(&options->monitor); + ffDestroyMouseOptions(&options->mouse); ffDestroyNetIOOptions(&options->netIo); ffDestroyOSOptions(&options->os); ffDestroyOpenCLOptions(&options->openCL); diff --git a/src/options/modules.h b/src/options/modules.h index 919d92408..4ff82f972 100644 --- a/src/options/modules.h +++ b/src/options/modules.h @@ -36,6 +36,7 @@ typedef struct FFOptionsModules FFIconsOptions icons; FFInitSystemOptions initSystem; FFKernelOptions kernel; + FFKeyboardOptions keyboard; FFLMOptions lm; FFLoadavgOptions loadavg; FFLocalIpOptions localIP; @@ -43,6 +44,7 @@ typedef struct FFOptionsModules FFMediaOptions media; FFMemoryOptions memory; FFMonitorOptions monitor; + FFMouseOptions mouse; FFNetIOOptions netIo; FFOSOptions os; FFOpenCLOptions openCL;