diff --git a/CMakeLists.txt b/CMakeLists.txt index 018d3375e..1eac66074 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,17 @@ if(MSYS) enable_language(CXX) endif() +############################# +# Compile time dependencies # +############################# + +set(THREADS_PREFER_PTHREAD_FLAG ON) +find_package(Threads) + +find_package(PkgConfig REQUIRED) + +include(CheckIncludeFile) + ##################### # Configure options # ##################### @@ -52,21 +63,11 @@ cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR BSD" OFF) cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR MSYS" OFF) cmake_dependent_option(ENABLE_LIBCJSON "Enable libcjson" ON "LINUX OR MSYS" OFF) cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF) +cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND AND NOT ANDROID" OFF) option(BUILD_TESTS "Build tests" OFF) # Also create test executables option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds -############################# -# Compile time dependencies # -############################# - -set(THREADS_PREFER_PTHREAD_FLAG ON) -find_package(Threads REQUIRED) - -find_package(PkgConfig REQUIRED) - -include(CheckIncludeFile) - #################### # Compiler options # #################### @@ -76,6 +77,15 @@ if(NOT CMAKE_BUILD_TYPE) endif() message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") +if(ENABLE_THREADS) + if(CMAKE_USE_PTHREADS_INIT) + message(STATUS "Threads type: pthread") + else() + message(STATUS "Threads type: Win32 thread") + endif() +else() + message(STATUS "Threads type: disabled") +endif() set(CMAKE_C_STANDARD 11) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wconversion") @@ -355,8 +365,8 @@ if(MSYS) src/detection/font/font_windows.cpp src/detection/terminalshell/terminalshell_linux.c src/detection/terminalshell/terminalshell_windows.cpp - src/detection/terminalfont/terminalfont_linux.c src/detection/packages/packages_linux.c + src/detection/terminalfont/terminalfont_windows.c src/detection/packages/packages_windows.c src/detection/kernel/kernel_windows.cpp src/detection/localip/localip_windows.c @@ -482,6 +492,11 @@ ff_lib_enable(OPENCL OpenCL) ff_lib_enable(LIBCJSON libcjson) ff_lib_enable(FREETYPE freetype2) +if(ENABLE_THREADS) + target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS) + target_link_libraries(libfastfetch PRIVATE Threads::Threads) +endif() + if(APPLE) target_link_libraries(libfastfetch PRIVATE "-framework CoreFoundation" @@ -501,6 +516,7 @@ elseif(MSYS) PRIVATE "opengl32" PRIVATE "gdi32" PRIVATE "iphlpapi" + PRIVATE "ws2_32" ) endif() @@ -511,7 +527,6 @@ target_include_directories(libfastfetch target_link_libraries(libfastfetch PRIVATE ${CMAKE_DL_LIBS} - PRIVATE Threads::Threads ) ###################### diff --git a/README.md b/README.md index f100921bb..b5282ea46 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,10 @@ There are some premade config files in [`presets`](presets), including the ones ## Dependencies -Fastfetch dynamically loads needed libraries if they are available. Therefore its only hard dependencies are `libc` (any implementation of the c standard library), `libdl` and `libpthread`. They are all shipped with [`glibc`](https://www.gnu.org/software/libc/), which is already installed on most linux distributions, so you probably don't have to worry about it. +Fastfetch dynamically loads needed libraries if they are available. Therefore its only hard dependencies are `libc` (any implementation of the c standard library), `libdl`. They are all shipped with [`glibc`](https://www.gnu.org/software/libc/), which is already installed on most linux distributions, so you probably don't have to worry about it. The following libraries are used if present at runtime: +* [`libpthread`](https://man7.org/linux/man-pages/man7/pthreads.7.html): For multithreading support, which may improve performance * [`libpci`](https://github.com/pciutils/pciutils): GPU output. * [`libvulkan`](https://www.vulkan.org/): Vulkan module & fallback for GPU output. * [`libxcb-randr`](https://xcb.freedesktop.org/), diff --git a/src/common/init.c b/src/common/init.c index be5dd73c1..f9001f12f 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -1,6 +1,7 @@ #include "fastfetch.h" #include "common/caching.h" #include "common/parsing.h" +#include "common/thread.h" #include "detection/qt.h" #include "detection/gtk.h" #include "detection/displayserver/displayserver.h" @@ -9,7 +10,6 @@ #include #include #include -#include static bool strbufEqualsAdapter(const void* first, const void* second) { @@ -259,87 +259,39 @@ void ffInitInstance(FFinstance* instance) defaultConfig(instance); } -#if !defined(__ANDROID__) && !defined(_WIN32) && !defined(__MSYS__) +#ifdef FF_HAVE_THREADS -static void* connectDisplayServerThreadMain(void* instance) -{ - ffConnectDisplayServer((FFinstance*)instance); - return NULL; -} +FF_THREAD_ENTRY_DECL_WRAPPER(ffConnectDisplayServer, FFinstance*) -#if !defined(__APPLE__) +#if !(defined(__APPLE__) || defined(__MSYS__) || defined(_WIN32)) -static void* detectPlasmaThreadMain(void* instance) -{ - ffDetectQt((FFinstance*)instance); - return NULL; -} +#define FF_DETECT_QT_GTK 1 -static void* detectGTK2ThreadMain(void* instance) -{ - ffDetectGTK2((FFinstance*)instance); - return NULL; -} +FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectQt, FFinstance*) +FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectGTK2, FFinstance*) +FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectGTK3, FFinstance*) +FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectGTK4, FFinstance*) -static void* detectGTK3ThreadMain(void* instance) -{ - ffDetectGTK3((FFinstance*)instance); - return NULL; -} +#endif //!(defined(__APPLE__) || defined(__MSYS__) || defined(_WIN32)) -static void* detectGTK4ThreadMain(void* instance) -{ - ffDetectGTK4((FFinstance*)instance); - return NULL; -} - -static void* startThreadsThreadMain(void* instance) -{ - pthread_t dsThread; - pthread_create(&dsThread, NULL, connectDisplayServerThreadMain, instance); - pthread_detach(dsThread); - - pthread_t gtk2Thread; - pthread_create(>k2Thread, NULL, detectGTK2ThreadMain, instance); - pthread_detach(gtk2Thread); - - pthread_t gtk3Thread; - pthread_create(>k3Thread, NULL, detectGTK3ThreadMain, instance); - pthread_detach(gtk3Thread); - - pthread_t gtk4Thread; - pthread_create(>k4Thread, NULL, detectGTK4ThreadMain, instance); - pthread_detach(gtk4Thread); - - pthread_t plasmaThread; - pthread_create(&plasmaThread, NULL, detectPlasmaThreadMain, instance); - pthread_detach(plasmaThread); - - return NULL; -} +#endif //FF_HAVE_THREADS void startDetectionThreads(FFinstance* instance) { - pthread_t startThreadsThread; - pthread_create(&startThreadsThread, NULL, startThreadsThreadMain, instance); - pthread_detach(startThreadsThread); -} + #ifdef FF_HAVE_THREADS + ffThreadCreateAndDetach(ffConnectDisplayServerThreadMain, instance); -#else // !__APPLE__ -void startDetectionThreads(FFinstance* instance) -{ - pthread_t startThreadsThread; - pthread_create(&startThreadsThread, NULL, connectDisplayServerThreadMain, instance); - pthread_detach(startThreadsThread); -} -#endif // __APPLE__ + #ifdef FF_DETECT_QT_GTK + ffThreadCreateAndDetach(ffDetectQtThreadMain, instance); + ffThreadCreateAndDetach(ffDetectGTK2ThreadMain, instance); + ffThreadCreateAndDetach(ffDetectGTK3ThreadMain, instance); + ffThreadCreateAndDetach(ffDetectGTK4ThreadMain, instance); + #endif -#else // !__ANDROID__ -void startDetectionThreads(FFinstance* instance) -{ + #else FF_UNUSED(instance); + #endif } -#endif // __ANDROID__ static volatile bool ffDisableLinewrap = true; static volatile bool ffHideCursor = true; diff --git a/src/common/networking.c b/src/common/networking.c index 4558f7f8e..d3685a543 100644 --- a/src/common/networking.c +++ b/src/common/networking.c @@ -1,13 +1,43 @@ +#if defined(_WIN32) || defined(__MSYS__) + #include + #include + #include + + static BOOL WINAPI initWsaData(PINIT_ONCE once, PVOID param, PVOID* context) + { + (void)once; + (void)param; + static WSADATA wsaData; + *context = &wsaData; + return WSAStartup(MAKEWORD(2, 2), &wsaData) == 0; + } + + //Types of winsock2 are full of mess. Disable warnings for them and keep clean for posix + #pragma GCC diagnostic ignored "-Wincompatible-pointer-types" + #pragma GCC diagnostic ignored "-Wconversion" + #pragma GCC diagnostic ignored "-Wsign-conversion" +#else + #include + #include + #include + #include + + #define closesocket close +#endif + +//Must be included after #include "fastfetch.h" #include "common/networking.h" -#include -#include -#include -#include - -int ffNetworkingSendHttpRequest(const char* host, const char* path, const char* headers, uint32_t timeout) +FFSockType ffNetworkingSendHttpRequest(const char* host, const char* path, const char* headers, uint32_t timeout) { + #if defined(_WIN32) || defined(__MSYS__) + static INIT_ONCE once = INIT_ONCE_STATIC_INIT; + WSADATA* pData; + if(!InitOnceExecuteOnce(&once, initWsaData, NULL, (LPVOID*) &pData)) + return INVALID_SOCKET; + #endif + struct addrinfo hints = { .ai_family = AF_INET, .ai_socktype = SOCK_STREAM, @@ -16,13 +46,13 @@ int ffNetworkingSendHttpRequest(const char* host, const char* path, const char* struct addrinfo* addr; if(getaddrinfo(host, "80", &hints, &addr) != 0) - return -1; + return INVALID_SOCKET; - int sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); - if(sockfd == -1) + FFSockType sockfd = (FFSockType)socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); + if(sockfd == INVALID_SOCKET) { freeaddrinfo(addr); - return -1; + return INVALID_SOCKET; } if(timeout > 0) @@ -35,9 +65,9 @@ int ffNetworkingSendHttpRequest(const char* host, const char* path, const char* if(connect(sockfd, addr->ai_addr, addr->ai_addrlen) == -1) { - close(sockfd); + closesocket(sockfd); freeaddrinfo(addr); - return -1; + return INVALID_SOCKET; } freeaddrinfo(addr); @@ -55,14 +85,14 @@ int ffNetworkingSendHttpRequest(const char* host, const char* path, const char* if(send(sockfd, command.chars, command.length, 0) == -1) { ffStrbufDestroy(&command); - close(sockfd); - return -1; + closesocket(sockfd); + return INVALID_SOCKET; } ffStrbufDestroy(&command); return sockfd; } -bool ffNetworkingRecvHttpResponse(int sockfd, FFstrbuf* buffer) +bool ffNetworkingRecvHttpResponse(FFSockType sockfd, FFstrbuf* buffer) { ssize_t received = recv(sockfd, buffer->chars + buffer->length, ffStrbufGetFree(buffer), 0); @@ -72,14 +102,14 @@ bool ffNetworkingRecvHttpResponse(int sockfd, FFstrbuf* buffer) buffer->chars[buffer->length] = '\0'; } - close(sockfd); + closesocket(sockfd); return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n"); } bool ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, const char* headers, FFstrbuf* buffer) { - int sockfd = ffNetworkingSendHttpRequest(host, path, headers, timeout); - if(sockfd > 0) + FFSockType sockfd = ffNetworkingSendHttpRequest(host, path, headers, timeout); + if(sockfd != INVALID_SOCKET) return ffNetworkingRecvHttpResponse(sockfd, buffer); return false; } diff --git a/src/common/networking.h b/src/common/networking.h index 145493ce7..f64288066 100644 --- a/src/common/networking.h +++ b/src/common/networking.h @@ -5,8 +5,18 @@ #include "util/FFstrbuf.h" -int ffNetworkingSendHttpRequest(const char* host, const char* path, const char* headers, uint32_t timeout); -bool ffNetworkingRecvHttpResponse(int sock, FFstrbuf* buffer); +#if defined(_WIN32) || defined(__MSYS__) + typedef uintptr_t FFSockType; //SOCKET, unsigned + #ifndef INVALID_SOCKET //Don't conflict with + #define INVALID_SOCKET ((uintptr_t)~0) + #endif +#else + typedef int FFSockType; // signed + #define INVALID_SOCKET (-1) +#endif + +FFSockType ffNetworkingSendHttpRequest(const char* host, const char* path, const char* headers, uint32_t timeout); +bool ffNetworkingRecvHttpResponse(FFSockType sockfd, FFstrbuf* buffer); bool ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, const char* headers, FFstrbuf* buffer); #endif diff --git a/src/common/properties.h b/src/common/properties.h index 38d79c2ec..dfdcad96e 100644 --- a/src/common/properties.h +++ b/src/common/properties.h @@ -3,7 +3,7 @@ #ifndef FF_INCLUDED_common_properties #define FF_INCLUDED_common_properties -#include "util/FFstrbuf.h" +#include "fastfetch.h" typedef struct FFpropquery { diff --git a/src/common/settings.c b/src/common/settings.c index 1b8a08c5d..6f5a5cfcb 100644 --- a/src/common/settings.c +++ b/src/common/settings.c @@ -2,8 +2,8 @@ #include "common/settings.h" #include "common/library.h" #include "common/io.h" +#include "common/thread.h" -#include #include typedef enum FFInitState @@ -15,18 +15,18 @@ typedef enum FFInitState #define FF_LIBRARY_DATA_LOAD_INIT(dataObject, userLibraryName, ...) \ static dataObject data; \ - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; \ + static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; \ static FFInitState initState = FF_INITSTATE_UNINITIALIZED; \ - pthread_mutex_lock(&mutex); \ + ffThreadMutexLock(&mutex); \ if(initState != FF_INITSTATE_UNINITIALIZED) {\ - pthread_mutex_unlock(&mutex); \ + ffThreadMutexUnlock(&mutex); \ return initState == FF_INITSTATE_SUCCESSFUL ? &data : NULL; \ } \ initState = FF_INITSTATE_SUCCESSFUL; \ void* libraryHandle = ffLibraryLoad(&userLibraryName, __VA_ARGS__, NULL); \ if(libraryHandle == NULL) { \ initState = FF_INITSTATE_FAILED; \ - pthread_mutex_unlock(&mutex); \ + ffThreadMutexUnlock(&mutex); \ return NULL; \ } \ @@ -35,20 +35,20 @@ typedef enum FFInitState if(data.ff ## symbolName == NULL) { \ dlclose(libraryHandle); \ initState = FF_INITSTATE_FAILED; \ - pthread_mutex_unlock(&mutex); \ + ffThreadMutexUnlock(&mutex); \ return NULL; \ } #define FF_LIBRARY_DATA_LOAD_RETURN \ initState = FF_INITSTATE_SUCCESSFUL; \ - pthread_mutex_unlock(&mutex); \ + ffThreadMutexUnlock(&mutex); \ return &data; #define FF_LIBRARY_DATA_LOAD_ERROR \ { \ dlclose(libraryHandle); \ initState = FF_INITSTATE_FAILED; \ - pthread_mutex_unlock(&mutex); \ + ffThreadMutexUnlock(&mutex); \ return NULL; \ } diff --git a/src/common/thread.h b/src/common/thread.h new file mode 100644 index 000000000..3c80f84fd --- /dev/null +++ b/src/common/thread.h @@ -0,0 +1,43 @@ +#pragma once + +#ifndef FF_INCLUDED_common_thread +#define FF_INCLUDED_common_thread + +#include "fastfetch.h" + +#ifdef FF_HAVE_THREADS + #if defined(_WIN32) + #include + #include + #include // Win32 isn't available on MSYS2 + #define FF_THREAD_MUTEX_INITIALIZER SRWLOCK_INIT + typedef SRWLOCK FFThreadMutex; + static inline void ffThreadMutexLock(FFThreadMutex* mutex) { AcquireSRWLockExclusive(mutex); } + static inline void ffThreadMutexUnlock(FFThreadMutex* mutex) { ReleaseSRWLockExclusive(mutex); } + static inline void ffThreadCreateAndDetach(__stdcall unsigned (* func)(void*), void* data) { + uintptr_t newThread = _beginthreadex(func, 0, data, NULL, 0, NULL); + if(newThread != 0) + CloseHandle((HANDLE)newThread); + } + #define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType) static __stdcall unsigned fn ## ThreadMain (void* data) { fn((paramType)data); return 0; } + #else + #include + #define FF_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER + typedef pthread_mutex_t FFThreadMutex; + static inline void ffThreadMutexLock(FFThreadMutex* mutex) { pthread_mutex_lock(mutex); } + static inline void ffThreadMutexUnlock(FFThreadMutex* mutex) { pthread_mutex_unlock(mutex); } + static inline void ffThreadCreateAndDetach(void* (* func)(void*), void* data) { + pthread_t newThread; + if(pthread_create(&newThread, NULL, func, data) == 0) + pthread_detach(newThread); + } + #define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType) static void* fn ## ThreadMain (void* data) { fn((paramType)data); return NULL; } + #endif +#else //FF_HAVE_THREADS + #define FF_THREAD_MUTEX_INITIALIZER 0 + typedef char FFThreadMutex; + static inline void ffThreadMutexLock(FFThreadMutex* mutex) { FF_UNUSED(mutex) } + static inline void ffThreadMutexUnlock(FFThreadMutex* mutex) { FF_UNUSED(mutex) } +#endif //FF_HAVE_THREADS + +#endif diff --git a/src/detection/datetime.c b/src/detection/datetime.c index 9c5ebf414..20b8ec367 100644 --- a/src/detection/datetime.c +++ b/src/detection/datetime.c @@ -1,21 +1,21 @@ #include "fastfetch.h" #include "detection/datetime.h" +#include "common/thread.h" #include -#include const FFDateTimeResult* ffDetectDateTime(const FFinstance* instance) { FF_UNUSED(instance); //We may need it later for additional configuration static FFDateTimeResult result; - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; static bool init = false; - pthread_mutex_lock(&mutex); + ffThreadMutexLock(&mutex); if (init) { - pthread_mutex_unlock(&mutex); + ffThreadMutexUnlock(&mutex); return &result; } init = true; @@ -68,6 +68,6 @@ const FFDateTimeResult* ffDetectDateTime(const FFinstance* instance) ffStrbufInitA(&result.secondPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC); result.secondPretty.length = (uint32_t) strftime(result.secondPretty.chars, ffStrbufGetFree(&result.secondPretty), "%S", tm); - pthread_mutex_unlock(&mutex); + ffThreadMutexUnlock(&mutex); return &result; } diff --git a/src/detection/disk/disk_apple.m b/src/detection/disk/disk_apple.m index b79d03e86..8341ef74e 100644 --- a/src/detection/disk/disk_apple.m +++ b/src/detection/disk/disk_apple.m @@ -1,5 +1,6 @@ #include "disk.h" +#include #import void ffDetectDiskWithStatvfs(const char* folderPath, struct statvfs* fs, FFDiskResult* result); diff --git a/src/detection/displayserver/linux/wayland.c b/src/detection/displayserver/linux/wayland.c index 39743282c..166ec25b2 100644 --- a/src/detection/displayserver/linux/wayland.c +++ b/src/detection/displayserver/linux/wayland.c @@ -6,7 +6,7 @@ #ifdef FF_HAVE_WAYLAND #include "common/library.h" #include "common/io.h" -#include +#include "common/thread.h" #include #include @@ -56,12 +56,12 @@ static void waylandOutputModeListener(void* data, struct wl_output* output, uint if(!(flags & WL_OUTPUT_MODE_CURRENT) || width <= 0 || height <= 0) return; - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - pthread_mutex_lock(&mutex); + static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; + ffThreadMutexLock(&mutex); FFResolutionResult* result = ffListAdd(wldata->results); - pthread_mutex_unlock(&mutex); + ffThreadMutexUnlock(&mutex); result->width = (uint32_t) width; result->height = (uint32_t) height; diff --git a/src/detection/gtk.c b/src/detection/gtk.c index 3855f7990..ad24c9c4e 100644 --- a/src/detection/gtk.c +++ b/src/detection/gtk.c @@ -1,11 +1,10 @@ #include "fastfetch.h" #include "detection/gtk.h" #include "common/properties.h" +#include "common/thread.h" #include "common/settings.h" #include "detection/displayserver/displayserver.h" -#include - static inline bool allPropertiesSet(FFGTKResult* result) { return @@ -34,7 +33,7 @@ static inline void applyGTKSettings(FFGTKResult* result, const char* themeName, static void detectGTKFromSettings(const FFinstance* instance, FFGTKResult* result) { - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; static const char* themeName = NULL; static const char* iconsName = NULL; @@ -44,11 +43,11 @@ static void detectGTKFromSettings(const FFinstance* instance, FFGTKResult* resul static bool init = false; - pthread_mutex_lock(&mutex); + ffThreadMutexLock(&mutex); if(init) { - pthread_mutex_unlock(&mutex); + ffThreadMutexUnlock(&mutex); applyGTKSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize); return; } @@ -90,7 +89,7 @@ static void detectGTKFromSettings(const FFinstance* instance, FFGTKResult* resul cursorSize = ffSettingsGet(instance, "/org/gnome/desktop/interface/cursor-size", "org.gnome.desktop.interface", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue; } - pthread_mutex_unlock(&mutex); + ffThreadMutexUnlock(&mutex); applyGTKSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize); } @@ -168,12 +167,12 @@ static void detectGTK(const FFinstance* instance, const char* version, FFGTKResu } #define FF_DETECT_GTK_IMPL(version) \ - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; \ + static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; \ static FFGTKResult result; \ static bool init = false; \ - pthread_mutex_lock(&mutex); \ + ffThreadMutexLock(&mutex); \ if(init){ \ - pthread_mutex_unlock(&mutex);\ + ffThreadMutexUnlock(&mutex);\ return &result; \ } \ init = true; \ @@ -183,7 +182,7 @@ static void detectGTK(const FFinstance* instance, const char* version, FFGTKResu ffStrbufInit(&result.cursor); \ ffStrbufInit(&result.cursorSize); \ detectGTK(instance, #version, &result); \ - pthread_mutex_unlock(&mutex); \ + ffThreadMutexUnlock(&mutex); \ return &result; const FFGTKResult* ffDetectGTK2(const FFinstance* instance) diff --git a/src/detection/internal.h b/src/detection/internal.h index f4dc67cbb..11b081f7e 100644 --- a/src/detection/internal.h +++ b/src/detection/internal.h @@ -3,21 +3,21 @@ #ifndef FF_INCLUDED_detection_internal #define FF_INCLUDED_detection_internal -#include "pthread.h" +#include "common/thread.h" #define FF_DETECTION_INTERNAL_GUARD(ResultType, ...) \ - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; \ + static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; \ static ResultType result; \ static bool init = false; \ - pthread_mutex_lock(&mutex); \ + ffThreadMutexLock(&mutex); \ if(init) \ { \ - pthread_mutex_unlock(&mutex); \ + ffThreadMutexUnlock(&mutex); \ return &result; \ } \ init = true; \ __VA_ARGS__; \ - pthread_mutex_unlock(&mutex); \ + ffThreadMutexUnlock(&mutex); \ return &result; \ #endif diff --git a/src/detection/media/media_linux.c b/src/detection/media/media_linux.c index 77ecbc3a9..60b407b99 100644 --- a/src/detection/media/media_linux.c +++ b/src/detection/media/media_linux.c @@ -1,8 +1,8 @@ #include "fastfetch.h" #include "detection/media/media.h" +#include "common/thread.h" #include -#include #define FF_DBUS_MPRIS_PREFIX "org.mpris.MediaPlayer2." #define FF_DBUS_TIMEOUT_MILLISECONDS 35 diff --git a/src/detection/qt.c b/src/detection/qt.c index 5bd9b2403..6a7794c8e 100644 --- a/src/detection/qt.c +++ b/src/detection/qt.c @@ -1,11 +1,11 @@ #include "fastfetch.h" #include "detection/qt.h" #include "common/properties.h" +#include "common/thread.h" #include "detection/displayserver/displayserver.h" #include #include -#include static inline bool allValuesSet(const FFQtResult* result) { @@ -135,12 +135,12 @@ const FFQtResult* ffDetectQt(const FFinstance* instance) { static FFQtResult result; - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; static bool init = false; - pthread_mutex_lock(&mutex); + ffThreadMutexLock(&mutex); if(init) { - pthread_mutex_unlock(&mutex); + ffThreadMutexUnlock(&mutex); return &result; } init = true; @@ -157,6 +157,6 @@ const FFQtResult* ffDetectQt(const FFinstance* instance) else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "LXQt") == 0) detectLXQt(instance, &result); - pthread_mutex_unlock(&mutex); + ffThreadMutexUnlock(&mutex); return &result; } diff --git a/src/detection/temps/temps_linux.c b/src/detection/temps/temps_linux.c index 5fad783d5..cb342a9f8 100644 --- a/src/detection/temps/temps_linux.c +++ b/src/detection/temps/temps_linux.c @@ -1,9 +1,9 @@ #include "fastfetch.h" #include "common/io.h" +#include "common/thread.h" #include "temps_linux.h" #include -#include #include static bool parseHwmonDir(FFstrbuf* dir, FFTempValue* value) @@ -38,13 +38,13 @@ static bool parseHwmonDir(FFstrbuf* dir, FFTempValue* value) const FFTempsResult* ffDetectTemps(const FFinstance* instance) { static FFTempsResult result; - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; static bool init = false; - pthread_mutex_lock(&mutex); + ffThreadMutexLock(&mutex); if(init) { - pthread_mutex_unlock(&mutex); + ffThreadMutexUnlock(&mutex); return &result; } init = true; @@ -52,7 +52,7 @@ const FFTempsResult* ffDetectTemps(const FFinstance* instance) if(!instance->config.allowSlowOperations) { ffListInitA(&result.values, sizeof(FFTempValue), 0); - pthread_mutex_unlock(&mutex); + ffThreadMutexUnlock(&mutex); return &result; } @@ -68,7 +68,7 @@ const FFTempsResult* ffDetectTemps(const FFinstance* instance) if(dirp == NULL) { ffStrbufDestroy(&baseDir); - pthread_mutex_unlock(&mutex); + ffThreadMutexUnlock(&mutex); return &result; } @@ -97,6 +97,6 @@ const FFTempsResult* ffDetectTemps(const FFinstance* instance) closedir(dirp); ffStrbufDestroy(&baseDir); - pthread_mutex_unlock(&mutex); + ffThreadMutexUnlock(&mutex); return &result; } diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 297301f2f..c79ed7827 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -64,6 +64,185 @@ static void detectTTY(FFTerminalFontResult* terminalFont) ffStrbufDestroy(&fontName); } +#if defined(_WIN32) || defined(__MSYS__) || defined(__linux__) +#ifdef FF_HAVE_LIBCJSON + +#include "common/library.h" +#include "common/processing.h" + +#include +#include + +typedef struct CJSONData +{ + FF_LIBRARY_SYMBOL(cJSON_Parse) + FF_LIBRARY_SYMBOL(cJSON_IsObject) + FF_LIBRARY_SYMBOL(cJSON_GetObjectItemCaseSensitive) + FF_LIBRARY_SYMBOL(cJSON_IsString) + FF_LIBRARY_SYMBOL(cJSON_GetStringValue) + FF_LIBRARY_SYMBOL(cJSON_IsNumber) + FF_LIBRARY_SYMBOL(cJSON_GetNumberValue) + FF_LIBRARY_SYMBOL(cJSON_IsArray) + FF_LIBRARY_SYMBOL(cJSON_Delete) +} CJSONData; + +static const char* detectWTProfile(CJSONData* cjsonData, cJSON* profile, FFstrbuf* name, int* size) +{ + if(!cjsonData->ffcJSON_IsObject(profile)) + return "cJSON_IsObject(profile) returns false"; + + cJSON* font = cjsonData->ffcJSON_GetObjectItemCaseSensitive(profile, "font"); + if(!cjsonData->ffcJSON_IsObject(font)) + return "cJSON_IsObject(font) returns false"; + + if(name->length == 0) + { + cJSON* pface = cjsonData->ffcJSON_GetObjectItemCaseSensitive(font, "face"); + if(cjsonData->ffcJSON_IsString(pface)) + ffStrbufAppendS(name, cjsonData->ffcJSON_GetStringValue(pface)); + } + if(*size < 0) + { + cJSON* psize = cjsonData->ffcJSON_GetObjectItemCaseSensitive(font, "size"); + if(cjsonData->ffcJSON_IsNumber(psize)) + *size = (int)cjsonData->ffcJSON_GetNumberValue(psize); + } + return NULL; +} + +static const char* detectFromWTImpl(const FFinstance* instance, FFstrbuf* content, FFstrbuf* name, int* size) +{ + CJSONData cjsonData; + + FF_LIBRARY_LOAD(libcjson, &instance->config.libcJSON, "dlopen libcjson"FF_LIBRARY_EXTENSION" failed", "libcjson"FF_LIBRARY_EXTENSION, 1) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_Parse) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsObject) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetObjectItemCaseSensitive) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsString) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetStringValue) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsNumber) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetNumberValue) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsArray) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_Delete) + + const char* error = NULL; + + cJSON* root = cjsonData.ffcJSON_Parse(content->chars); + if(!cjsonData.ffcJSON_IsObject(root)) + { + error = "cJSON_Parse() failed"; + goto exit; + } + + cJSON* profiles = cjsonData.ffcJSON_GetObjectItemCaseSensitive(root, "profiles"); + if(!cjsonData.ffcJSON_IsObject(profiles)) + { + error = "cJSON_GetObjectItemCaseSensitive(root, \"profiles\") failed"; + goto exit; + } + + FFstrbuf wtProfileId; + ffStrbufInitS(&wtProfileId, getenv("WT_PROFILE_ID")); + ffStrbufTrim(&wtProfileId, '\''); + if(wtProfileId.length > 0) + { + cJSON* list = cjsonData.ffcJSON_GetObjectItemCaseSensitive(profiles, "list"); + if(cjsonData.ffcJSON_IsArray(list)) + { + cJSON* profile; + cJSON_ArrayForEach(profile, list) + { + if(!cjsonData.ffcJSON_IsObject(profile)) + continue; + cJSON* guid = cjsonData.ffcJSON_GetObjectItemCaseSensitive(profile, "guid"); + if(!cjsonData.ffcJSON_IsString(guid)) + continue; + if(ffStrbufCompS(&wtProfileId, cjsonData.ffcJSON_GetStringValue(guid)) == 0) + { + detectWTProfile(&cjsonData, profile, name, size); + break; + } + } + } + } + ffStrbufDestroy(&wtProfileId); + + cJSON* defaults = cjsonData.ffcJSON_GetObjectItemCaseSensitive(profiles, "defaults"); + detectWTProfile(&cjsonData, defaults, name, size); + + if(name->length == 0) + ffStrbufSetS(name, "Cascadia Mono"); + if(*size < 0) + *size = 12; + +exit: + cjsonData.ffcJSON_Delete(root); + dlclose(libcjson); + return error; +} + +static void detectFromWindowsTeriminal(const FFinstance* instance, FFTerminalFontResult* terminalFont) +{ + //https://learn.microsoft.com/en-us/windows/terminal/install#settings-json-file + FFstrbuf json; + ffStrbufInit(&json); + const char* error; + error = ffProcessAppendStdOut(&json, (char* const[]) { + "cmd.exe", + "/c", + //print the file content directly, so we don't need to handle the difference of Windows and POSIX path + "if exist %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminal_8wekyb3d8bbwe\\LocalState\\settings.json " + "( type %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminal_8wekyb3d8bbwe\\LocalState\\settings.json ) " + "else if exist %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe\\LocalState\\settings.json " + "( type %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe\\LocalState\\settings.json ) " + "else if exist \"%LOCALAPPDATA%\\Microsoft\\Windows Terminal\\settings.json\" " + "( type %LOCALAPPDATA%\\Microsoft\\Windows Terminal\\settings.json ) " + "else ( call )", + NULL + }); + if(error) + { + ffStrbufAppendS(&terminalFont->error, error); + ffStrbufDestroy(&json); + return; + } + ffStrbufTrimRight(&json, '\n'); + if(json.length == 0) + { + ffStrbufAppendS(&terminalFont->error, "Cannot find file \"settings.json\""); + ffStrbufDestroy(&json); + return; + } + + FFstrbuf name; + ffStrbufInit(&name); + int size = -1; + error = detectFromWTImpl(instance, &json, &name, &size); + ffStrbufDestroy(&json); + + if(error) + ffStrbufAppendS(&terminalFont->error, error); + else + { + char sizeStr[16]; + snprintf(sizeStr, sizeof(sizeStr), "%d", size); + ffFontInitValues(&terminalFont->font, name.chars, sizeStr); + } + + ffStrbufDestroy(&name); +} + +#else + +static void detectFromWindowsTeriminal(const FFinstance* instance, FFTerminalFontResult* terminalFont) +{ + FF_UNUSED(instance, terminalFont); + ffStrbufAppendS(&terminalFont->error, "fastfetch is built without libcjson support"); +} + +#endif +#endif //defined(_WIN32) || defined(__MSYS__) || defined(__linux__) + void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont); const FFTerminalFontResult* ffDetectTerminalFont(const FFinstance* instance) @@ -79,6 +258,14 @@ const FFTerminalFontResult* ffDetectTerminalFont(const FFinstance* instance) detectAlacritty(instance, &result); else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalExe, "/dev/tty")) detectTTY(&result); + + #if defined(_WIN32) || defined(__MSYS__) || defined(__linux__) + //Used by both Linux (WSL) and Windows + else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "Windows Terminal") == 0 || + ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "WindowsTerminal.exe") == 0) + detectFromWindowsTeriminal(instance, &result); + #endif + else ffDetectTerminalFontPlatform(instance, terminalShell, &result); diff --git a/src/detection/terminalfont/terminalfont_linux.c b/src/detection/terminalfont/terminalfont_linux.c index 06a71da50..e63ccd815 100644 --- a/src/detection/terminalfont/terminalfont_linux.c +++ b/src/detection/terminalfont/terminalfont_linux.c @@ -140,259 +140,6 @@ static void detectXFCETerminal(const FFinstance* instance, FFTerminalFontResult* ffStrbufDestroy(&useSysFont); } -#ifdef FF_HAVE_LIBCJSON - -#include "common/library.h" -#include "common/processing.h" - -#include -#include - -typedef struct CJSONData -{ - FF_LIBRARY_SYMBOL(cJSON_Parse) - FF_LIBRARY_SYMBOL(cJSON_IsObject) - FF_LIBRARY_SYMBOL(cJSON_GetObjectItemCaseSensitive) - FF_LIBRARY_SYMBOL(cJSON_IsString) - FF_LIBRARY_SYMBOL(cJSON_GetStringValue) - FF_LIBRARY_SYMBOL(cJSON_IsNumber) - FF_LIBRARY_SYMBOL(cJSON_GetNumberValue) - FF_LIBRARY_SYMBOL(cJSON_IsArray) - FF_LIBRARY_SYMBOL(cJSON_Delete) -} CJSONData; - -static const char* detectWTProfile(CJSONData* cjsonData, cJSON* profile, FFstrbuf* name, int* size) -{ - if(!cjsonData->ffcJSON_IsObject(profile)) - return "cJSON_IsObject(profile) returns false"; - - cJSON* font = cjsonData->ffcJSON_GetObjectItemCaseSensitive(profile, "font"); - if(!cjsonData->ffcJSON_IsObject(font)) - return "cJSON_IsObject(font) returns false"; - - if(name->length == 0) - { - cJSON* pface = cjsonData->ffcJSON_GetObjectItemCaseSensitive(font, "face"); - if(cjsonData->ffcJSON_IsString(pface)) - ffStrbufAppendS(name, cjsonData->ffcJSON_GetStringValue(pface)); - } - if(*size < 0) - { - cJSON* psize = cjsonData->ffcJSON_GetObjectItemCaseSensitive(font, "size"); - if(cjsonData->ffcJSON_IsNumber(psize)) - *size = (int)cjsonData->ffcJSON_GetNumberValue(psize); - } - return NULL; -} - -static const char* detectFromWTImpl(const FFinstance* instance, FFstrbuf* content, FFstrbuf* name, int* size) -{ - CJSONData cjsonData; - - FF_LIBRARY_LOAD(libcjson, &instance->config.libcJSON, "dlopen libcjson"FF_LIBRARY_EXTENSION" failed", "libcjson"FF_LIBRARY_EXTENSION, 1) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_Parse) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsObject) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetObjectItemCaseSensitive) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsString) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetStringValue) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsNumber) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetNumberValue) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsArray) - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_Delete) - - const char* error = NULL; - - cJSON* root = cjsonData.ffcJSON_Parse(content->chars); - if(!cjsonData.ffcJSON_IsObject(root)) - { - error = "cJSON_Parse() failed"; - goto exit; - } - - cJSON* profiles = cjsonData.ffcJSON_GetObjectItemCaseSensitive(root, "profiles"); - if(!cjsonData.ffcJSON_IsObject(profiles)) - { - error = "cJSON_GetObjectItemCaseSensitive(root, \"profiles\") failed"; - goto exit; - } - - FFstrbuf wtProfileId; - ffStrbufInitS(&wtProfileId, getenv("WT_PROFILE_ID")); - ffStrbufTrim(&wtProfileId, '\''); - if(wtProfileId.length > 0) - { - cJSON* list = cjsonData.ffcJSON_GetObjectItemCaseSensitive(profiles, "list"); - if(cjsonData.ffcJSON_IsArray(list)) - { - cJSON* profile; - cJSON_ArrayForEach(profile, list) - { - if(!cjsonData.ffcJSON_IsObject(profile)) - continue; - cJSON* guid = cjsonData.ffcJSON_GetObjectItemCaseSensitive(profile, "guid"); - if(!cjsonData.ffcJSON_IsString(guid)) - continue; - if(ffStrbufCompS(&wtProfileId, cjsonData.ffcJSON_GetStringValue(guid)) == 0) - { - detectWTProfile(&cjsonData, profile, name, size); - break; - } - } - } - } - ffStrbufDestroy(&wtProfileId); - - cJSON* defaults = cjsonData.ffcJSON_GetObjectItemCaseSensitive(profiles, "defaults"); - detectWTProfile(&cjsonData, defaults, name, size); - - if(name->length == 0) - ffStrbufSetS(name, "Cascadia Mono"); - if(*size < 0) - *size = 12; - -exit: - cjsonData.ffcJSON_Delete(root); - dlclose(libcjson); - return error; -} - -static void detectFromWindowsTeriminal(const FFinstance* instance, FFTerminalFontResult* terminalFont) -{ - //https://learn.microsoft.com/en-us/windows/terminal/install#settings-json-file - FFstrbuf json; - ffStrbufInit(&json); - const char* error; - error = ffProcessAppendStdOut(&json, (char* const[]) { - "cmd.exe", - "/c", - //print the file content directly, so we don't need to handle the difference of Windows and POSIX path - "if exist %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminal_8wekyb3d8bbwe\\LocalState\\settings.json " - "( type %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminal_8wekyb3d8bbwe\\LocalState\\settings.json ) " - "else if exist %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe\\LocalState\\settings.json " - "( type %LOCALAPPDATA%\\Packages\\Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe\\LocalState\\settings.json ) " - "else if exist \"%LOCALAPPDATA%\\Microsoft\\Windows Terminal\\settings.json\" " - "( type %LOCALAPPDATA%\\Microsoft\\Windows Terminal\\settings.json ) " - "else ( call )", - NULL - }); - if(error) - { - ffStrbufAppendS(&terminalFont->error, error); - ffStrbufDestroy(&json); - return; - } - ffStrbufTrimRight(&json, '\n'); - if(json.length == 0) - { - ffStrbufAppendS(&terminalFont->error, "Cannot find file \"settings.json\""); - ffStrbufDestroy(&json); - return; - } - - FFstrbuf name; - ffStrbufInit(&name); - int size = -1; - error = detectFromWTImpl(instance, &json, &name, &size); - ffStrbufDestroy(&json); - - if(error) - ffStrbufAppendS(&terminalFont->error, error); - else - { - char sizeStr[16]; - snprintf(sizeStr, sizeof(sizeStr), "%d", size); - ffFontInitValues(&terminalFont->font, name.chars, sizeStr); - } - - ffStrbufDestroy(&name); -} - -#else - -static void detectFromWindowsTeriminal(const FFinstance* instance, FFTerminalFontResult* terminalFont) -{ - FF_UNUSED(instance, terminalFont); - ffStrbufAppendS(&terminalFont->error, "fastfetch is built without libcjson support"); -} - -#endif - -#if defined(_WIN32) || defined(__MSYS__) -// TODO: move to a separate file - -static void detectMintty(const FFinstance* instance, FFTerminalFontResult* terminalFont) -{ - FFstrbuf fontName; - ffStrbufInit(&fontName); - - FFstrbuf fontSize; - ffStrbufInit(&fontSize); - - ffParsePropFileHomeValues(instance, ".minttyrc", 2, (FFpropquery[]) { - {"Font=", &fontName}, - {"FontHeight=", &fontSize} - }); - if(fontName.length == 0) - ffStrbufAppendS(&fontName, "Lucida Console"); - if(fontSize.length == 0) - ffStrbufAppendC(&fontSize, '9'); - - ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars); - - ffStrbufDestroy(&fontName); - ffStrbufDestroy(&fontSize); -} - -#define WIN32_LEAN_AND_MEAN 1 -#include - -static void detectConhost(const FFinstance* instance, FFTerminalFontResult* terminalFont) -{ - FF_UNUSED(instance); - - //Current font of conhost doesn't seem to be detectable, we detect default font instead - - HKEY hKey; - if(RegOpenKeyExW(HKEY_CURRENT_USER, L"Console", 0, KEY_READ, &hKey) != ERROR_SUCCESS) - { - ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW() failed"); - return; - } - - DWORD bufSize; - - wchar_t fontNameW[64]; - bufSize = sizeof(fontNameW); - if(RegQueryValueExW(hKey, L"FaceName", NULL, NULL, (LPBYTE)fontNameW, &bufSize) != ERROR_SUCCESS) - { - ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW(FaceName) failed"); - goto exit; - } - fontNameW[bufSize] = '\0'; - - char fontNameA[128]; - int fontNameALen = WideCharToMultiByte(CP_UTF8, 0, fontNameW, (int)(bufSize / 2), fontNameA, sizeof(fontNameA), NULL, NULL); - fontNameA[fontNameALen] = '\0'; - - uint32_t fontSizeNum = 0; - bufSize = sizeof(fontSizeNum); - if(RegQueryValueExW(hKey, L"fontSize", NULL, NULL, (LPBYTE)&fontSizeNum, &bufSize) != ERROR_SUCCESS) - { - ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW(fontSize) failed"); - goto exit; - } - - char fontSize[16]; - snprintf(fontSize, sizeof(fontSize), "%u", (fontSizeNum >> 16)); - - ffFontInitValues(&terminalFont->font, fontNameA, fontSize); - -exit: - RegCloseKey(hKey); -} - -#endif //defined(_WIN32) || defined(__MSYS__) - void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont) { if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "konsole") == 0) @@ -405,14 +152,4 @@ void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalSh detectFromGSettings(instance, "/com/gexperts/Tilix/profiles/", "com.gexperts.Tilix.ProfilesList", "com.gexperts.Tilix.Profile", terminalFont); else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "gnome-terminal-") == 0) detectFromGSettings(instance, "/org/gnome/terminal/legacy/profiles:/:", "org.gnome.Terminal.ProfilesList", "org.gnome.Terminal.Legacy.Profile", terminalFont); - else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "Windows Terminal") == 0 || - ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "WindowsTerminal.exe") == 0) - detectFromWindowsTeriminal(instance, terminalFont); - - #if defined(_WIN32) || defined(__MSYS__) - else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "mintty") == 0) - detectMintty(instance, terminalFont); - else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "conhost.exe") == 0) - detectConhost(instance, terminalFont); - #endif } diff --git a/src/detection/terminalfont/terminalfont_windows.c b/src/detection/terminalfont/terminalfont_windows.c new file mode 100644 index 000000000..6a68bb6a5 --- /dev/null +++ b/src/detection/terminalfont/terminalfont_windows.c @@ -0,0 +1,82 @@ +#include "common/properties.h" +#include "detection/terminalshell/terminalshell.h" +#include "terminalfont.h" + +#define WIN32_LEAN_AND_MEAN 1 +#include + +static void detectMintty(const FFinstance* instance, FFTerminalFontResult* terminalFont) +{ + FFstrbuf fontName; + ffStrbufInit(&fontName); + + FFstrbuf fontSize; + ffStrbufInit(&fontSize); + + ffParsePropFileHomeValues(instance, ".minttyrc", 2, (FFpropquery[]) { + {"Font=", &fontName}, + {"FontHeight=", &fontSize} + }); + if(fontName.length == 0) + ffStrbufAppendS(&fontName, "Lucida Console"); + if(fontSize.length == 0) + ffStrbufAppendC(&fontSize, '9'); + + ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars); + + ffStrbufDestroy(&fontName); + ffStrbufDestroy(&fontSize); +} + +static void detectConhost(const FFinstance* instance, FFTerminalFontResult* terminalFont) +{ + FF_UNUSED(instance); + + //Current font of conhost doesn't seem to be detectable, we detect default font instead + + HKEY hKey; + if(RegOpenKeyExW(HKEY_CURRENT_USER, L"Console", 0, KEY_READ, &hKey) != ERROR_SUCCESS) + { + ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW() failed"); + return; + } + + DWORD bufSize; + + wchar_t fontNameW[64]; + bufSize = sizeof(fontNameW); + if(RegQueryValueExW(hKey, L"FaceName", NULL, NULL, (LPBYTE)fontNameW, &bufSize) != ERROR_SUCCESS) + { + ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW(FaceName) failed"); + goto exit; + } + fontNameW[bufSize] = '\0'; + + char fontNameA[128]; + int fontNameALen = WideCharToMultiByte(CP_UTF8, 0, fontNameW, (int)(bufSize / 2), fontNameA, sizeof(fontNameA), NULL, NULL); + fontNameA[fontNameALen] = '\0'; + + uint32_t fontSizeNum = 0; + bufSize = sizeof(fontSizeNum); + if(RegQueryValueExW(hKey, L"fontSize", NULL, NULL, (LPBYTE)&fontSizeNum, &bufSize) != ERROR_SUCCESS) + { + ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW(fontSize) failed"); + goto exit; + } + + char fontSize[16]; + snprintf(fontSize, sizeof(fontSize), "%u", (fontSizeNum >> 16)); + + ffFontInitValues(&terminalFont->font, fontNameA, fontSize); + +exit: + RegCloseKey(hKey); +} + +void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont) +{ + if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "mintty") == 0) + detectMintty(instance, terminalFont); + else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "conhost.exe") == 0) + detectConhost(instance, terminalFont); +} diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index b5f68c58f..534c343c7 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -3,13 +3,13 @@ #include "common/io.h" #include "common/parsing.h" #include "common/processing.h" +#include "common/thread.h" #include "terminalshell.h" #include #include #include #include -#include #ifdef __APPLE__ #include @@ -318,13 +318,13 @@ const FFTerminalShellResult* { FF_UNUSED(instance); - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; static FFTerminalShellResult result; static bool init = false; - pthread_mutex_lock(&mutex); + ffThreadMutexLock(&mutex); if(init) { - pthread_mutex_unlock(&mutex); + ffThreadMutexUnlock(&mutex); return &result; } init = true; @@ -361,6 +361,6 @@ const FFTerminalShellResult* else ffStrbufInitCopy(&result.terminalPrettyName, &result.terminalProcessName); - pthread_mutex_unlock(&mutex); + ffThreadMutexUnlock(&mutex); return &result; } diff --git a/src/detection/title.c b/src/detection/title.c index b4394be15..df9367ba0 100644 --- a/src/detection/title.c +++ b/src/detection/title.c @@ -1,16 +1,17 @@ #include "fastfetch.h" #include "detection/title.h" +#include "common/thread.h" #include #include -#include -#include #ifndef HOST_NAME_MAX #define HOST_NAME_MAX 64 #endif #ifdef __linux__ +#include + static void detectFQDN(FFTitleResult* title) { struct addrinfo hints = {0}; @@ -37,12 +38,12 @@ const FFTitleResult* ffDetectTitle(const FFinstance* instance) { static FFTitleResult result; - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; static bool init = false; - pthread_mutex_lock(&mutex); + ffThreadMutexLock(&mutex); if(init) { - pthread_mutex_unlock(&mutex); + ffThreadMutexUnlock(&mutex); return &result; } init = true; @@ -54,12 +55,12 @@ const FFTitleResult* ffDetectTitle(const FFinstance* instance) ffStrbufAppendS(&result.hostname, instance->state.utsname.nodename); ffStrbufInitA(&result.fqdn, HOST_NAME_MAX); - #ifdef __linux + #ifdef __linux__ detectFQDN(&result); #endif if(result.fqdn.length == 0) ffStrbufAppend(&result.fqdn, &result.hostname); - pthread_mutex_unlock(&mutex); + ffThreadMutexUnlock(&mutex); return &result; } diff --git a/src/detection/vulkan.c b/src/detection/vulkan.c index 1ff96e2c9..9c348b74b 100644 --- a/src/detection/vulkan.c +++ b/src/detection/vulkan.c @@ -1,9 +1,8 @@ #include "fastfetch.h" +#include "common/thread.h" #include "detection/vulkan.h" #include "detection/gpu/gpu.h" -#include - #ifdef FF_HAVE_VULKAN #include "common/library.h" #include "common/io.h" @@ -217,13 +216,13 @@ static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* resu const FFVulkanResult* ffDetectVulkan(const FFinstance* instance) { static FFVulkanResult result; - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; static bool init = false; - pthread_mutex_lock(&mutex); + ffThreadMutexLock(&mutex); if(init) { - pthread_mutex_unlock(&mutex); + ffThreadMutexUnlock(&mutex); return &result; } init = true; @@ -240,6 +239,6 @@ const FFVulkanResult* ffDetectVulkan(const FFinstance* instance) result.error = "fastfetch was compiled without vulkan support"; #endif - pthread_mutex_unlock(&mutex); + ffThreadMutexUnlock(&mutex); return &result; } diff --git a/src/modules/publicip.c b/src/modules/publicip.c index fe77e30f6..019f13dfb 100644 --- a/src/modules/publicip.c +++ b/src/modules/publicip.c @@ -5,7 +5,7 @@ #define FF_PUBLICIP_MODULE_NAME "Public IP" #define FF_PUBLICIP_NUM_FORMAT_ARGS 1 -static int sockfd; +static FFSockType sockfd; void ffPreparePublicIp(FFinstance* instance) { @@ -39,7 +39,7 @@ void ffPrintPublicIp(FFinstance* instance) if(sockfd == 0) ffPreparePublicIp(instance); - if(sockfd < 0) + if(sockfd == INVALID_SOCKET) { ffPrintError(instance, FF_PUBLICIP_MODULE_NAME, 0, &instance->config.publicIP, "Failed to connect to an IP detection server"); return; diff --git a/src/modules/weather.c b/src/modules/weather.c index 43c1d56fd..11dc9748e 100644 --- a/src/modules/weather.c +++ b/src/modules/weather.c @@ -5,7 +5,7 @@ #define FF_WEATHER_MODULE_NAME "Weather" #define FF_WEATHER_NUM_FORMAT_ARGS 1 -static int sockfd; +static FFSockType sockfd; void ffPrepareWeather(FFinstance* instance) { @@ -21,7 +21,7 @@ void ffPrintWeather(FFinstance* instance) if(sockfd == 0) ffPrepareWeather(instance); - if(sockfd < 0) + if(sockfd == INVALID_SOCKET) { ffPrintError(instance, FF_WEATHER_MODULE_NAME, 0, &instance->config.weather, "Failed to connect to 'wttr.in'"); return;