mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-11-06 13:14:21 +01:00
@@ -7,6 +7,8 @@ project(fastfetch
|
||||
HOMEPAGE_URL "https://github.com/LinusDierheimer/fastfetch"
|
||||
)
|
||||
|
||||
set(PROJECT_LICENSE "MIT license")
|
||||
|
||||
###################
|
||||
# Target Platform #
|
||||
###################
|
||||
@@ -578,6 +580,26 @@ target_link_libraries(flashfetch
|
||||
PRIVATE libfastfetch
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
if(PROJECT_VERSION_TWEAK)
|
||||
string(REGEX MATCH "[0-9]+" PROJECT_VERSION_TWEAK_NUM "${PROJECT_VERSION_TWEAK}")
|
||||
else()
|
||||
set(PROJECT_VERSION_TWEAK_NUM "0")
|
||||
endif()
|
||||
|
||||
set(TARGET_NAME fastfetch)
|
||||
configure_file(src/util/windows/version.rc.in version.fastfetch.rc)
|
||||
target_sources(fastfetch
|
||||
PRIVATE version.fastfetch.rc
|
||||
)
|
||||
|
||||
set(TARGET_NAME flashfetch)
|
||||
configure_file(src/util/windows/version.rc.in version.flashfetch.rc)
|
||||
target_sources(flashfetch
|
||||
PRIVATE version.flashfetch.rc
|
||||
)
|
||||
endif()
|
||||
|
||||
###################
|
||||
# Testing targets #
|
||||
###################
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Fastfetch
|
||||
|
||||
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying them in a pretty way. It is written in pure c, with performance and customizability in mind. Currently Linux, Android, FreeBSD, MacOS and Windows are supported.
|
||||
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying them in a pretty way. It is written in pure c, with performance and customizability in mind. Currently Linux, Android, FreeBSD, MacOS and Windows 7+ are supported.
|
||||
|
||||
<img src="screenshots/example1.png" width="49%" align="left" />
|
||||
<img src="https://upload.wikimedia.org/wikipedia/commons/2/24/Transparent_Square_Tiles_Texture.png" width="49%" height="16px" align="left" />
|
||||
@@ -61,6 +61,8 @@ The following libraries are used if present at runtime:
|
||||
* [`libvulkan`](https://www.vulkan.org/): Vulkan module. Usually has been provided by GPU drivers.
|
||||
* [`libOpenCL`](https://www.khronos.org/opencl/): OpenCL module
|
||||
|
||||
Note: On Windows 10-, [ConEmu](https://conemu.github.io/en/AnsiEscapeCodes.html) is required to run fastfetch due to [the lack of ASCII escape code native support](https://en.wikipedia.org/wiki/ANSI_escape_code#DOS,_OS/2,_and_Windows). Also make sure to [use `chcp 65001` to enable UTF-8 support](https://conemu.github.io/en/UnicodeSupport.html#utf-8) if you run Windows locale other than English.
|
||||
|
||||
### Android
|
||||
|
||||
* [`freetype`](https://www.freetype.org/): Used for Termux font detection.
|
||||
@@ -101,7 +103,7 @@ KDE Plasma, Gnome, Cinnamon, Mate, XFCE4, LXQt
|
||||
|
||||
##### Terminal fonts
|
||||
```
|
||||
Konsole, Gnome Terminal, Tilix, XFCE4 Terminal, Alacritty, LXTerminal, iTerm2, Apple Terminal, TTY, Windows Terminal, Termux, mintty
|
||||
Konsole, Gnome Terminal, Tilix, XFCE4 Terminal, Alacritty, LXTerminal, iTerm2, Apple Terminal, Warp, TTY, Windows Terminal, Termux, mintty, ConEmu
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
+7
-5
@@ -334,12 +334,9 @@ static void resetConsole()
|
||||
#ifdef _WIN32
|
||||
BOOL WINAPI consoleHandler(DWORD signal)
|
||||
{
|
||||
if(signal == CTRL_C_EVENT)
|
||||
{
|
||||
FF_UNUSED(signal);
|
||||
resetConsole();
|
||||
return TRUE;
|
||||
}
|
||||
return false;
|
||||
exit(0);
|
||||
}
|
||||
#else
|
||||
static void exitSignalHandler(int signal)
|
||||
@@ -360,6 +357,11 @@ void ffStart(FFinstance* instance)
|
||||
|
||||
#ifdef _WIN32
|
||||
SetConsoleCtrlHandler(consoleHandler, TRUE);
|
||||
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DWORD mode = 0;
|
||||
GetConsoleMode(hStdout, &mode);
|
||||
SetConsoleMode(hStdout, mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
|
||||
// SetConsoleOutputCP(CP_UTF8);
|
||||
#else
|
||||
struct sigaction action = { .sa_handler = exitSignalHandler };
|
||||
sigaction(SIGINT, &action, NULL);
|
||||
|
||||
@@ -67,7 +67,7 @@ bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, con
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
state->thread = ffThreadCreate(connectAndSendThreadMain, state);
|
||||
return state->thread != NULL;
|
||||
return !!state->thread;
|
||||
#else
|
||||
connectAndSend(state);
|
||||
return state->sockfd != -1;
|
||||
|
||||
@@ -75,7 +75,7 @@ bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, con
|
||||
}
|
||||
}
|
||||
|
||||
FFstrbuf command;
|
||||
FF_STRBUF_AUTO_DESTROY command;
|
||||
ffStrbufInitA(&command, 64);
|
||||
ffStrbufAppendS(&command, "GET ");
|
||||
ffStrbufAppendS(&command, path);
|
||||
@@ -87,7 +87,6 @@ bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, con
|
||||
|
||||
BOOL result = ConnectEx(state->sockfd, addr->ai_addr, (int)addr->ai_addrlen, command.chars, command.length, NULL, &state->overlapped);
|
||||
freeaddrinfo(addr);
|
||||
ffStrbufDestroy(&command);
|
||||
|
||||
if(!result && WSAGetLastError() != WSA_IO_PENDING)
|
||||
{
|
||||
@@ -95,7 +94,6 @@ bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, con
|
||||
return false;
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&command);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,28 +27,31 @@ const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
|
||||
.hStdOutput = hChildStdoutWrite,
|
||||
};
|
||||
|
||||
FFstrbuf cmdline;
|
||||
ffStrbufInitF(&cmdline, "\"%s\"", argv[0]);
|
||||
for(char* const* parg = &argv[1]; *parg; ++parg)
|
||||
BOOL success;
|
||||
|
||||
{
|
||||
ffStrbufAppendC(&cmdline, ' ');
|
||||
ffStrbufAppendS(&cmdline, *parg);
|
||||
FF_STRBUF_AUTO_DESTROY cmdline;
|
||||
ffStrbufInitF(&cmdline, "\"%s\"", argv[0]);
|
||||
for(char* const* parg = &argv[1]; *parg; ++parg)
|
||||
{
|
||||
ffStrbufAppendC(&cmdline, ' ');
|
||||
ffStrbufAppendS(&cmdline, *parg);
|
||||
}
|
||||
|
||||
success = CreateProcessA(
|
||||
NULL, // application name
|
||||
cmdline.chars, // command line
|
||||
NULL, // process security attributes
|
||||
NULL, // primary thread security attributes
|
||||
TRUE, // handles are inherited
|
||||
0, // creation flags
|
||||
NULL, // use parent's environment
|
||||
NULL, // use parent's current directory
|
||||
&siStartInfo, // STARTUPINFO pointer
|
||||
&piProcInfo // receives PROCESS_INFORMATION
|
||||
);
|
||||
}
|
||||
|
||||
BOOL success = CreateProcessA(
|
||||
NULL, // application name
|
||||
cmdline.chars, // command line
|
||||
NULL, // process security attributes
|
||||
NULL, // primary thread security attributes
|
||||
TRUE, // handles are inherited
|
||||
0, // creation flags
|
||||
NULL, // use parent's environment
|
||||
NULL, // use parent's current directory
|
||||
&siStartInfo, // STARTUPINFO pointer
|
||||
&piProcInfo); // receives PROCESS_INFORMATION
|
||||
|
||||
ffStrbufDestroy(&cmdline);
|
||||
|
||||
CloseHandle(hChildStdoutWrite);
|
||||
if(!success)
|
||||
{
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@
|
||||
static inline void ffThreadMutexLock(FFThreadMutex* mutex) { pthread_mutex_lock(mutex); }
|
||||
static inline void ffThreadMutexUnlock(FFThreadMutex* mutex) { pthread_mutex_unlock(mutex); }
|
||||
static inline FFThreadType ffThreadCreate(void* (* func)(void*), void* data) {
|
||||
FFThreadType newThread = NULL;
|
||||
FFThreadType newThread = 0;
|
||||
pthread_create(&newThread, NULL, func, data);
|
||||
return newThread;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
static double detectBatteryTemp()
|
||||
{
|
||||
FFlist temps;
|
||||
FF_LIST_AUTO_DESTROY temps;
|
||||
ffListInit(&temps, sizeof(FFTempValue));
|
||||
|
||||
ffDetectCoreTemps(FF_TEMP_BATTERY, &temps);
|
||||
@@ -25,7 +25,6 @@ static double detectBatteryTemp()
|
||||
ffStrbufDestroy(&tempValue->deviceClass);
|
||||
}
|
||||
result /= temps.length;
|
||||
ffListDestroy(&temps);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ static void detectCPU(const FFinstance* instance, FFCPUResult* cpu)
|
||||
return;
|
||||
|
||||
const char* removeStrings[] = {
|
||||
"(R)", "(r)", "(TM)", "(tm)",
|
||||
" CPU", " FPU", " APU", " Processor",
|
||||
" Dual-Core", " Quad-Core", " Six-Core", " Eight-Core", " Ten-Core",
|
||||
" 2-Core", " 4-Core", " 6-Core", " 8-Core", " 10-Core", " 12-Core", " 14-Core", " 16-Core",
|
||||
|
||||
@@ -15,7 +15,7 @@ static double getFrequency(const char* propName)
|
||||
|
||||
static double detectCpuTemp(const FFstrbuf* cpuName)
|
||||
{
|
||||
FFlist temps;
|
||||
FF_LIST_AUTO_DESTROY temps;
|
||||
ffListInit(&temps, sizeof(FFTempValue));
|
||||
|
||||
if(ffStrbufStartsWithS(cpuName, "Apple M1"))
|
||||
@@ -38,7 +38,6 @@ static double detectCpuTemp(const FFstrbuf* cpuName)
|
||||
ffStrbufDestroy(&tempValue->deviceClass);
|
||||
}
|
||||
result /= temps.length;
|
||||
ffListDestroy(&temps);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,11 +17,21 @@ void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu, bool cached)
|
||||
ffStrbufInit(&cpu->name);
|
||||
ffStrbufInit(&cpu->vendor);
|
||||
|
||||
FFWmiQuery query(L"SELECT Name, Manufacturer, NumberOfCores, NumberOfLogicalProcessors, ThreadCount, CurrentClockSpeed, MaxClockSpeed FROM Win32_Processor WHERE ProcessorType = 3");
|
||||
FFWmiQuery query(L"SELECT Name, Manufacturer, NumberOfCores, NumberOfLogicalProcessors, NumberOfEnabledCore, CurrentClockSpeed, MaxClockSpeed FROM Win32_Processor WHERE ProcessorType = 3");
|
||||
if(!query)
|
||||
return;
|
||||
|
||||
if(FFWmiRecord record = query.next())
|
||||
FFWmiRecord record = query.next();
|
||||
if(!record)
|
||||
{
|
||||
//NumberOfEnabledCore is not supported on Windows 10-
|
||||
query = FFWmiQuery(L"SELECT Name, Manufacturer, NumberOfCores, NumberOfLogicalProcessors, CurrentClockSpeed, MaxClockSpeed FROM Win32_Processor WHERE ProcessorType = 3");
|
||||
if(!query)
|
||||
return;
|
||||
record = query.next();
|
||||
}
|
||||
|
||||
if(record)
|
||||
{
|
||||
record.getString(L"Name", &cpu->name);
|
||||
record.getString(L"Manufacturer", &cpu->vendor);
|
||||
@@ -32,8 +42,7 @@ void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu, bool cached)
|
||||
cpu->coresPhysical = (uint16_t)value;
|
||||
record.getUnsigned(L"NumberOfLogicalProcessors", &value);
|
||||
cpu->coresLogical = (uint16_t)value;
|
||||
record.getUnsigned(L"ThreadCount", &value);
|
||||
cpu->coresOnline = (uint16_t)value;
|
||||
cpu->coresOnline = record.getUnsigned(L"NumberOfEnabledCore", &value) ? (uint16_t)value : cpu->coresPhysical;
|
||||
record.getUnsigned(L"CurrentClockSpeed", &value); //There's no MinClockSpeed in Win32_Processor
|
||||
cpu->frequencyMin = (double)value / 1000.0;
|
||||
record.getUnsigned(L"MaxClockSpeed", &value);
|
||||
|
||||
@@ -36,23 +36,30 @@ const char* ffGetCpuUsageResult(double* result)
|
||||
error = ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
|
||||
if(error)
|
||||
return error;
|
||||
ffTimeSleep(1000);
|
||||
ffTimeSleep(250);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t duration = ffTimeGetTick() - startTime;
|
||||
if(duration < 1000)
|
||||
ffTimeSleep(1000 - (uint32_t) duration);
|
||||
if(duration < 250)
|
||||
ffTimeSleep(250 - (uint32_t) duration);
|
||||
}
|
||||
|
||||
uint64_t inUseAll2, totalAll2;
|
||||
error = ffGetCpuUsageInfo(&inUseAll2, &totalAll2);
|
||||
if(error)
|
||||
return error;
|
||||
while(true)
|
||||
{
|
||||
uint64_t inUseAll2, totalAll2;
|
||||
error = ffGetCpuUsageInfo(&inUseAll2, &totalAll2);
|
||||
if(error)
|
||||
return error;
|
||||
|
||||
*result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100;
|
||||
|
||||
return NULL;
|
||||
if(inUseAll2 != inUseAll1)
|
||||
{
|
||||
*result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100;
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
ffTimeSleep(250);
|
||||
}
|
||||
}
|
||||
|
||||
#endif //FF_DETECTION_CPUUSAGE_NOWAIT
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#include "fastfetch.h"
|
||||
#include "cpuUsage.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <Windows.h>
|
||||
#include <processthreadsapi.h>
|
||||
|
||||
static inline uint64_t fileTimeToUint64(const FILETIME* ft) {
|
||||
return (((uint64_t)ft->dwHighDateTime) << 32) | ((uint64_t)ft->dwLowDateTime);
|
||||
@@ -11,10 +10,12 @@ static inline uint64_t fileTimeToUint64(const FILETIME* ft) {
|
||||
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
|
||||
{
|
||||
FILETIME idleTime, kernelTime, userTime;
|
||||
if(GetSystemTimes(&idleTime, &kernelTime, &userTime) == 0)
|
||||
if(!GetSystemTimes(&idleTime, &kernelTime, &userTime))
|
||||
return "GetSystemTimes() failed";
|
||||
|
||||
*inUseAll = fileTimeToUint64(&userTime) + fileTimeToUint64(&kernelTime);
|
||||
*totalAll = *inUseAll + fileTimeToUint64(&idleTime);
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getsystemtimes
|
||||
// `kernelTime` also includes the amount of time the system has been idle.
|
||||
*totalAll = fileTimeToUint64(&userTime) + fileTimeToUint64(&kernelTime);
|
||||
*inUseAll = *totalAll - fileTimeToUint64(&idleTime);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -73,9 +73,15 @@ void ffDetectDisksImpl(FFDiskResult* disks)
|
||||
#endif
|
||||
|
||||
//Detects stats
|
||||
struct statvfs fs;
|
||||
if(statvfs(disk->mountpoint.chars, &fs) != 0)
|
||||
memset(&fs, 0, sizeof(struct statvfs)); //Set all values to 0, so our values get initialized to 0 too
|
||||
#ifdef __USE_LARGEFILE64
|
||||
struct statvfs64 fs;
|
||||
if(statvfs64(disk->mountpoint.chars, &fs) != 0)
|
||||
memset(&fs, 0, sizeof(struct statvfs64)); //Set all values to 0, so our values get initialized to 0 too
|
||||
#else
|
||||
struct statvfs fs;
|
||||
if(statvfs(disk->mountpoint.chars, &fs) != 0)
|
||||
memset(&fs, 0, sizeof(struct statvfs)); //Set all values to 0, so our values get initialized to 0 too
|
||||
#endif
|
||||
|
||||
disk->bytesTotal = fs.f_blocks * fs.f_frsize;
|
||||
disk->bytesUsed = disk->bytesTotal - (fs.f_bavail * fs.f_frsize);
|
||||
|
||||
@@ -4,53 +4,31 @@
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
|
||||
//Resolution code heavily inspired by displayplacer <3
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint8_t rawData[0xDC];
|
||||
struct
|
||||
{
|
||||
uint32_t mode;
|
||||
uint32_t flags; // 0x4
|
||||
uint32_t width; // 0x8
|
||||
uint32_t height; // 0xC
|
||||
uint32_t depth; // 0x10
|
||||
uint32_t dc2[42];
|
||||
uint16_t dc3;
|
||||
uint16_t freq; // 0xBC
|
||||
uint32_t dc4[4];
|
||||
float density; // 0xD0
|
||||
} derived;
|
||||
} modes_D4;
|
||||
|
||||
void CGSGetCurrentDisplayMode(CGDirectDisplayID display, int* modeNum);
|
||||
void CGSGetDisplayModeDescriptionOfLength(CGDirectDisplayID display, int idx, modes_D4* mode, int length);
|
||||
#include <assert.h>
|
||||
#include <CoreGraphics/CGDirectDisplay.h>
|
||||
|
||||
static void detectResolution(FFDisplayServerResult* ds)
|
||||
{
|
||||
CGDisplayCount screenCount;
|
||||
CGGetOnlineDisplayList(INT_MAX, NULL, &screenCount);
|
||||
if(screenCount == 0)
|
||||
CGDirectDisplayID screens[128];
|
||||
uint32_t screenCount;
|
||||
if(CGGetOnlineDisplayList(sizeof(screens) / sizeof(screens[0]), screens, &screenCount) != kCGErrorSuccess)
|
||||
return;
|
||||
|
||||
CGDirectDisplayID* screens = malloc(screenCount * sizeof(CGDirectDisplayID));
|
||||
CGGetOnlineDisplayList(INT_MAX, screens, &screenCount);
|
||||
|
||||
for(uint32_t i = 0; i < screenCount; i++)
|
||||
{
|
||||
int modeID;
|
||||
CGSGetCurrentDisplayMode(screens[i], &modeID);
|
||||
modes_D4 mode;
|
||||
CGSGetDisplayModeDescriptionOfLength(screens[i], modeID, &mode, 0xD4);
|
||||
|
||||
uint32_t refreshRate = ffdsParseRefreshRate(mode.derived.freq);
|
||||
ffdsAppendResolution(ds, mode.derived.width, mode.derived.height, refreshRate);
|
||||
CGDirectDisplayID screen = screens[i];
|
||||
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(screen);
|
||||
if(mode)
|
||||
{
|
||||
ffdsAppendResolution(ds,
|
||||
(uint32_t)CGDisplayModeGetWidth(mode),
|
||||
(uint32_t)CGDisplayModeGetHeight(mode),
|
||||
(uint32_t)CGDisplayModeGetRefreshRate(mode)
|
||||
);
|
||||
CGDisplayModeRelease(mode);
|
||||
}
|
||||
CGDisplayRelease(screen);
|
||||
}
|
||||
|
||||
free(screens);
|
||||
}
|
||||
|
||||
static void detectWM(FFDisplayServerResult* ds)
|
||||
|
||||
@@ -12,10 +12,10 @@ typedef struct FFFontResult
|
||||
FFstrbuf error;
|
||||
|
||||
/**
|
||||
* Linux / BSD: QT, GTK2, GTK3, GTK4
|
||||
* MacOS: System, User, Monospace, Application
|
||||
* Windows: Desktop, Unset, Unset, Unset
|
||||
* Other: Unset, Unset, Unset, Unset
|
||||
* Linux / BSD: QT, GTK2, GTK3, GTK4
|
||||
* MacOS: System, User, System Mono, User Mono
|
||||
* Windows: Desktop, Unset, Unset, Unset
|
||||
* Other: Unset, Unset, Unset, Unset
|
||||
*/
|
||||
FFstrbuf fonts[FF_DETECT_FONT_NUM_FONTS];
|
||||
} FFFontResult;
|
||||
|
||||
@@ -1,23 +1,14 @@
|
||||
#include "common/font.h"
|
||||
#include "common/io.h"
|
||||
#include "util/apple/cf_helpers.h"
|
||||
#include "font.h"
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
static void detectFontForType(CTFontUIFontType uiType, FFstrbuf* font)
|
||||
{
|
||||
CTFontRef ctFont = CTFontCreateUIFontForLanguage(uiType, 12, NULL);
|
||||
ffCfStrGetString(CTFontCopyFamilyName(ctFont), font);
|
||||
}
|
||||
#import <AppKit/NSFont.h>
|
||||
|
||||
void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
ffSuppressIO(true);
|
||||
detectFontForType(kCTFontUIFontSystem, &result->fonts[0]);
|
||||
detectFontForType(kCTFontUIFontUser, &result->fonts[1]);
|
||||
detectFontForType(kCTFontUIFontUserFixedPitch, &result->fonts[2]);
|
||||
detectFontForType(kCTFontUIFontApplication, &result->fonts[3]);
|
||||
ffSuppressIO(false);
|
||||
ffStrbufAppendS(&result->fonts[0], [NSFont systemFontOfSize:12].familyName.UTF8String);
|
||||
ffStrbufAppendS(&result->fonts[1], [NSFont userFontOfSize:12].familyName.UTF8String);
|
||||
ffStrbufAppendS(&result->fonts[2], [NSFont monospacedSystemFontOfSize:12 weight:400].familyName.UTF8String);
|
||||
ffStrbufAppendS(&result->fonts[3], [NSFont userFixedPitchFontOfSize:12].familyName.UTF8String);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
|
||||
|
||||
if(FFWmiRecord record = query.next())
|
||||
{
|
||||
FFstrbuf fontName;
|
||||
FF_STRBUF_AUTO_DESTROY fontName;
|
||||
ffStrbufInit(&fontName);
|
||||
record.getString(L"IconTitleFaceName", &fontName);
|
||||
|
||||
@@ -26,8 +26,6 @@ void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
|
||||
record.getUnsigned(L"IconTitleSize", &fontSize);
|
||||
|
||||
ffStrbufAppendF(&result->fonts[0], "%*s (%upt)", fontName.length, fontName.chars, (unsigned)fontSize);
|
||||
|
||||
ffStrbufDestroy(&fontName);
|
||||
}
|
||||
else
|
||||
ffStrbufInitS(&result->error, "No WMI result returned");
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
static double detectGpuTemp(const FFstrbuf* gpuName)
|
||||
{
|
||||
FFlist temps;
|
||||
FF_LIST_AUTO_DESTROY temps;
|
||||
ffListInit(&temps, sizeof(FFTempValue));
|
||||
|
||||
if(ffStrbufStartsWithS(gpuName, "Apple M1"))
|
||||
@@ -35,7 +35,6 @@ static double detectGpuTemp(const FFstrbuf* gpuName)
|
||||
ffStrbufDestroy(&tempValue->deviceClass);
|
||||
}
|
||||
result /= temps.length;
|
||||
ffListDestroy(&temps);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_HOST_PRODUCT_NAME_WSL "Windows Subsystem for Linux"
|
||||
#define FF_HOST_PRODUCT_NAME_MSYS "Windows on MSYS"
|
||||
|
||||
typedef struct FFHostResult
|
||||
{
|
||||
FFstrbuf productFamily;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "host.h"
|
||||
#include "common/io.h"
|
||||
#include "common/processing.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -94,6 +95,27 @@ void ffDetectHostImpl(FFHostResult* host)
|
||||
{
|
||||
//On WSL, the real host can't be detected. Instead use WSL as host.
|
||||
if(getenv("WSL_DISTRO") != NULL || getenv("WSL_INTEROP") != NULL)
|
||||
ffStrbufAppendS(&host->productName, FF_HOST_PRODUCT_NAME_WSL);
|
||||
{
|
||||
ffStrbufAppendS(&host->productName, "Windows Subsystem for Linux");
|
||||
|
||||
FFstrbuf wslVer; //Wide charactors
|
||||
ffStrbufInit(&wslVer);
|
||||
if(!ffProcessAppendStdOut(&wslVer, (char* const[]){
|
||||
"wsl.exe",
|
||||
"--version",
|
||||
NULL
|
||||
}) && wslVer.length > 0)
|
||||
{
|
||||
ffStrbufSubstrBeforeFirstC(&wslVer, '\r'); //CRLF
|
||||
ffStrbufSubstrAfterLastC(&wslVer, ' ');
|
||||
ffStrbufAppendS(&host->productName, " (");
|
||||
for(uint32_t i = 0; i < wslVer.length; ++i) {
|
||||
if(wslVer.chars[i]) //don't append \0
|
||||
ffStrbufAppendC(&host->productName, wslVer.chars[i]);
|
||||
}
|
||||
ffStrbufAppendC(&host->productName, ')');
|
||||
}
|
||||
ffStrbufDestroy(&wslVer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,5 +28,5 @@ extern "C" void ffDetectHostImpl(FFHostResult* host)
|
||||
record.getString(L"Vendor", &host->sysVendor);
|
||||
}
|
||||
else
|
||||
ffStrbufInitS(&host->error, "No Wmi result returned");
|
||||
ffStrbufAppendS(&host->error, "No Wmi result returned");
|
||||
}
|
||||
|
||||
@@ -5,14 +5,11 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
ffStrbufInit(&os->name);
|
||||
ffStrbufSetS(&os->name, "Android");
|
||||
ffStrbufInitS(&os->name, "Android");
|
||||
|
||||
ffStrbufInit(&os->prettyName);
|
||||
ffStrbufSetS(&os->prettyName, "Android");
|
||||
ffStrbufInitS(&os->prettyName, "Android");
|
||||
|
||||
ffStrbufInit(&os->id);
|
||||
ffStrbufSetS(&os->id, "android");
|
||||
ffStrbufInitS(&os->id, "android");
|
||||
|
||||
ffStrbufInit(&os->version);
|
||||
ffSettingsGetAndroidProperty("ro.build.version.release", &os->version);
|
||||
@@ -26,13 +23,11 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance)
|
||||
ffStrbufInit(&os->buildID);
|
||||
ffSettingsGetAndroidProperty("ro.build.id", &os->buildID);
|
||||
|
||||
ffStrbufInit(&os->systemName);
|
||||
ffStrbufSetS(&os->systemName, instance->state.utsname.sysname);
|
||||
ffStrbufInitS(&os->systemName, instance->state.utsname.sysname);
|
||||
|
||||
ffStrbufInit(&os->architecture);
|
||||
ffStrbufSetS(&os->architecture, instance->state.utsname.machine);
|
||||
ffStrbufInitS(&os->architecture, instance->state.utsname.machine);
|
||||
|
||||
ffStrbufInitA(&os->idLike, 0);
|
||||
ffStrbufInitA(&os->variant, 0);
|
||||
ffStrbufInitA(&os->variantID, 0);
|
||||
ffStrbufInit(&os->idLike);
|
||||
ffStrbufInit(&os->variant);
|
||||
ffStrbufInit(&os->variantID);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance)
|
||||
if(FFWmiRecord record = query.next())
|
||||
{
|
||||
record.getString(L"Caption", &os->variant);
|
||||
ffStrbufTrimRight(&os->variant, ' ');
|
||||
if(ffStrbufStartsWithS(&os->variant, "Microsoft Windows "))
|
||||
{
|
||||
ffStrbufAppendS(&os->name, "Microsoft Windows");
|
||||
|
||||
@@ -27,7 +27,7 @@ static uint32_t getNumElements(const char* dirname, unsigned char type)
|
||||
|
||||
static uint32_t countBrewPackages(const char* dirname)
|
||||
{
|
||||
FFstrbuf baseDir;
|
||||
FF_STRBUF_AUTO_DESTROY baseDir;
|
||||
ffStrbufInitS(&baseDir, dirname);
|
||||
|
||||
uint32_t result = 0;
|
||||
@@ -41,7 +41,6 @@ static uint32_t countBrewPackages(const char* dirname)
|
||||
result += getNumElements(baseDir.chars, DT_DIR);
|
||||
ffStrbufSubstrBefore(&baseDir, baseDirLength);
|
||||
|
||||
ffStrbufDestroy(&baseDir);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -59,14 +58,11 @@ static uint32_t getBrewPackages()
|
||||
|
||||
static uint32_t countMacPortsPackages(const char* dirname)
|
||||
{
|
||||
FFstrbuf baseDir;
|
||||
FF_STRBUF_AUTO_DESTROY baseDir;
|
||||
ffStrbufInitS(&baseDir, dirname);
|
||||
ffStrbufAppendS(&baseDir, "/var/macports/software");
|
||||
|
||||
uint32_t result = getNumElements(baseDir.chars, DT_DIR);
|
||||
|
||||
ffStrbufDestroy(&baseDir);
|
||||
return result;
|
||||
return getNumElements(baseDir.chars, DT_DIR);
|
||||
}
|
||||
|
||||
static uint32_t getMacPortsPackages()
|
||||
|
||||
@@ -104,12 +104,11 @@ static uint32_t smcStrtoul(const char *str, int size, int base)
|
||||
|
||||
static void smcUltostr(char *str, uint32_t val)
|
||||
{
|
||||
str[0] = '\0';
|
||||
sprintf(str, "%c%c%c%c",
|
||||
(unsigned int)val >> 24,
|
||||
(unsigned int)val >> 16,
|
||||
(unsigned int)val >> 8,
|
||||
(unsigned int)val);
|
||||
str[0] = (char)(val >> 24);
|
||||
str[1] = (char)(val >> 16);
|
||||
str[2] = (char)(val >> 8);
|
||||
str[3] = (char)val;
|
||||
str[4] = '\0';
|
||||
}
|
||||
|
||||
static const char *smcCall(io_connect_t conn, uint32_t selector, SmcKeyData_t *inputStructure, SmcKeyData_t *outputStructure)
|
||||
|
||||
@@ -31,7 +31,7 @@ const char* detectTermux(const FFinstance* instance, FFTerminalFontResult* termi
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if(ffFT_New_Face(library, FF_TERMUX_FONT_PATH, 0, &face ))
|
||||
if(ffFT_New_Face(library, FF_TERMUX_FONT_PATH, 0, &face))
|
||||
{
|
||||
error = "FT_NEW_Face(" FF_TERMUX_FONT_PATH ") failed";
|
||||
goto exit;
|
||||
@@ -49,7 +49,7 @@ exit:
|
||||
#else
|
||||
|
||||
FF_UNUSED(terminalFont);
|
||||
ffStrbufSetS(&terminalFont->error, "fastfetch is built without freetype2 support");
|
||||
return "fastfetch is built without freetype2 support";
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ static void detectIterm2(const FFinstance* instance, FFTerminalFontResult* termi
|
||||
error:&error];
|
||||
if(error)
|
||||
{
|
||||
ffStrbufAppendS(&terminalFont->error, [error localizedDescription].UTF8String);
|
||||
ffStrbufAppendS(&terminalFont->error, error.localizedDescription.UTF8String);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -46,25 +46,42 @@ static void detectIterm2(const FFinstance* instance, FFTerminalFontResult* termi
|
||||
|
||||
static void detectAppleTerminal(FFTerminalFontResult* terminalFont)
|
||||
{
|
||||
FFstrbuf fontName;
|
||||
ffStrbufInit(&fontName);
|
||||
ffOsascript("tell application \"Terminal\" to font name of window frontmost", &fontName);
|
||||
FF_STRBUF_AUTO_DESTROY font;
|
||||
ffStrbufInit(&font);
|
||||
ffOsascript("tell application \"Terminal\" to font name of window frontmost & \" \" & font size of window frontmost", &font);
|
||||
|
||||
if(fontName.length == 0)
|
||||
if(font.length == 0)
|
||||
{
|
||||
ffStrbufAppendS(&terminalFont->error, "executing osascript failed");
|
||||
ffStrbufDestroy(&fontName);
|
||||
return;
|
||||
}
|
||||
|
||||
FFstrbuf fontSize;
|
||||
ffStrbufInit(&fontSize);
|
||||
ffOsascript("tell application \"Terminal\" to font size of window frontmost", &fontSize);
|
||||
ffFontInitWithSpace(&terminalFont->font, font.chars);
|
||||
}
|
||||
|
||||
ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars);
|
||||
static void detectWarpTerminal(const FFinstance* instance, FFTerminalFontResult* terminalFont)
|
||||
{
|
||||
NSError* error;
|
||||
NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/dev.warp.Warp-Stable.plist", instance->state.passwd->pw_dir];
|
||||
NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:fileName]
|
||||
error:&error];
|
||||
if(error)
|
||||
{
|
||||
ffStrbufAppendS(&terminalFont->error, error.localizedDescription.UTF8String);
|
||||
return;
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&fontName);
|
||||
ffStrbufDestroy(&fontSize);
|
||||
NSString* fontName = [dict valueForKey:@"FontName"];
|
||||
if(!fontName)
|
||||
fontName = @"Hack";
|
||||
else
|
||||
fontName = [fontName stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\""]];
|
||||
|
||||
NSString* fontSize = [dict valueForKey:@"FontSize"];
|
||||
if(!fontSize)
|
||||
fontSize = @"13";
|
||||
|
||||
ffFontInitValues(&terminalFont->font, fontName.UTF8String, fontSize.UTF8String);
|
||||
}
|
||||
|
||||
void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont)
|
||||
@@ -73,4 +90,6 @@ void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalSh
|
||||
detectIterm2(instance, terminalFont);
|
||||
else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "Apple_Terminal") == 0)
|
||||
detectAppleTerminal(terminalFont);
|
||||
else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "WarpTerminal") == 0)
|
||||
detectWarpTerminal(instance, terminalFont);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "common/properties.h"
|
||||
#include "common/io.h"
|
||||
#include "detection/terminalshell/terminalshell.h"
|
||||
#include "terminalfont.h"
|
||||
|
||||
@@ -7,10 +8,10 @@
|
||||
|
||||
static void detectMintty(const FFinstance* instance, FFTerminalFontResult* terminalFont)
|
||||
{
|
||||
FFstrbuf fontName;
|
||||
FF_STRBUF_AUTO_DESTROY fontName;
|
||||
ffStrbufInit(&fontName);
|
||||
|
||||
FFstrbuf fontSize;
|
||||
FF_STRBUF_AUTO_DESTROY fontSize;
|
||||
ffStrbufInit(&fontSize);
|
||||
|
||||
ffParsePropFileHomeValues(instance, ".minttyrc", 2, (FFpropquery[]) {
|
||||
@@ -23,9 +24,12 @@ static void detectMintty(const FFinstance* instance, FFTerminalFontResult* termi
|
||||
ffStrbufAppendC(&fontSize, '9');
|
||||
|
||||
ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars);
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&fontName);
|
||||
ffStrbufDestroy(&fontSize);
|
||||
static inline void wrapRegCloseKey(HKEY* phKey)
|
||||
{
|
||||
if(*phKey)
|
||||
RegCloseKey(*phKey);
|
||||
}
|
||||
|
||||
static void detectConhost(const FFinstance* instance, FFTerminalFontResult* terminalFont)
|
||||
@@ -34,7 +38,7 @@ static void detectConhost(const FFinstance* instance, FFTerminalFontResult* term
|
||||
|
||||
//Current font of conhost doesn't seem to be detectable, we detect default font instead
|
||||
|
||||
HKEY hKey;
|
||||
HKEY __attribute__((__cleanup__(wrapRegCloseKey))) hKey = NULL;
|
||||
if(RegOpenKeyExW(HKEY_CURRENT_USER, L"Console", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
|
||||
{
|
||||
ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW() failed");
|
||||
@@ -43,34 +47,78 @@ static void detectConhost(const FFinstance* instance, FFTerminalFontResult* term
|
||||
|
||||
DWORD bufSize;
|
||||
|
||||
wchar_t fontNameW[64];
|
||||
bufSize = sizeof(fontNameW);
|
||||
if(RegQueryValueExW(hKey, L"FaceName", NULL, NULL, (LPBYTE)fontNameW, &bufSize) != ERROR_SUCCESS)
|
||||
char fontName[128];
|
||||
bufSize = sizeof(fontName);
|
||||
if(RegGetValueA(hKey, NULL, "FaceName", RRF_RT_REG_SZ, NULL, fontName, &bufSize) != ERROR_SUCCESS)
|
||||
{
|
||||
ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW(FaceName) failed");
|
||||
goto exit;
|
||||
ffStrbufAppendS(&terminalFont->error, "RegGetValueA(FaceName) failed");
|
||||
return;
|
||||
}
|
||||
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)
|
||||
if(RegGetValueW(hKey, NULL, L"FontSize", RRF_RT_DWORD, NULL, &fontSizeNum, &bufSize) != ERROR_SUCCESS)
|
||||
{
|
||||
ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW(fontSize) failed");
|
||||
goto exit;
|
||||
ffStrbufAppendS(&terminalFont->error, "RegGetValueW(FontSize) failed");
|
||||
return;
|
||||
}
|
||||
|
||||
char fontSize[16];
|
||||
snprintf(fontSize, sizeof(fontSize), "%u", (fontSizeNum >> 16));
|
||||
_ultoa((unsigned long)(fontSizeNum >> 16), fontSize, 10);
|
||||
|
||||
ffFontInitValues(&terminalFont->font, fontNameA, fontSize);
|
||||
ffFontInitValues(&terminalFont->font, fontName, fontSize);
|
||||
}
|
||||
|
||||
exit:
|
||||
RegCloseKey(hKey);
|
||||
static void detectConEmu(const FFinstance* instance, FFTerminalFontResult* terminalFont)
|
||||
{
|
||||
FF_UNUSED(instance)
|
||||
|
||||
//https://conemu.github.io/en/ConEmuXml.html#search-sequence
|
||||
FFstrbuf path;
|
||||
ffStrbufInit(&path);
|
||||
|
||||
FFstrbuf fontName;
|
||||
ffStrbufInit(&fontName);
|
||||
|
||||
FFstrbuf fontSize;
|
||||
ffStrbufInit(&fontSize);
|
||||
|
||||
const char* paths[] = { "ConEmuDir", "ConEmuBaseDir", "APPDATA" };
|
||||
for (uint32_t i = 0; i < sizeof(paths) / sizeof(paths[0]); ++i)
|
||||
{
|
||||
ffStrbufSetS(&path, getenv(paths[i]));
|
||||
if(path.length > 0)
|
||||
{
|
||||
ffStrbufAppendS(&path, "/ConEmu.xml");
|
||||
if(ffParsePropFileValues(path.chars, 2, (FFpropquery[]){
|
||||
{"<value name=\"FontName\" type=\"string\" data=\"", &fontName},
|
||||
{"<value name=\"FontSize\" type=\"ulong\" data=\"", &fontSize}
|
||||
}))
|
||||
break;
|
||||
}
|
||||
}
|
||||
ffStrbufDestroy(&path);
|
||||
|
||||
if(fontName.length == 0 && fontSize.length == 0)
|
||||
{
|
||||
ffStrbufAppendS(&terminalFont->error, "Failed to parse ConEmu.xml");
|
||||
return;
|
||||
}
|
||||
|
||||
if(fontName.length > 0)
|
||||
ffStrbufSubstrBeforeLastC(&fontName, '"');
|
||||
else
|
||||
ffStrbufAppendS(&fontName, "Consola");
|
||||
|
||||
if(fontSize.length > 0)
|
||||
ffStrbufSubstrBeforeLastC(&fontSize, '"');
|
||||
else
|
||||
ffStrbufAppendS(&fontSize, "14");
|
||||
|
||||
ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars);
|
||||
|
||||
ffStrbufDestroy(&fontName);
|
||||
ffStrbufDestroy(&fontSize);
|
||||
}
|
||||
|
||||
void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont)
|
||||
@@ -79,4 +127,6 @@ void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalSh
|
||||
detectMintty(instance, terminalFont);
|
||||
else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "conhost.exe") == 0)
|
||||
detectConhost(instance, terminalFont);
|
||||
else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "ConEmuC"))
|
||||
detectConEmu(instance, terminalFont);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "fastfetch.h"
|
||||
#include "detection/host/host.h"
|
||||
#include "common/io.h"
|
||||
#include "common/parsing.h"
|
||||
#include "common/processing.h"
|
||||
@@ -180,10 +179,17 @@ static void getTerminalFromEnv(FFTerminalShellResult* result)
|
||||
if(
|
||||
result->terminalProcessName.length > 0 &&
|
||||
!ffStrbufStartsWithIgnCaseS(&result->terminalProcessName, "login") &&
|
||||
ffStrbufIgnCaseCompS(&result->terminalProcessName, "(login)") != 0 &&
|
||||
ffStrbufIgnCaseCompS(&result->terminalProcessName, "systemd") != 0 &&
|
||||
ffStrbufIgnCaseCompS(&result->terminalProcessName, "init") != 0 &&
|
||||
ffStrbufIgnCaseCompS(&result->terminalProcessName, "(init)") != 0 &&
|
||||
!ffStrbufIgnCaseEqualS(&result->terminalProcessName, "(login)") &&
|
||||
|
||||
#ifdef __APPLE__
|
||||
!ffStrbufIgnCaseEqualS(&result->terminalProcessName, "launchd") &&
|
||||
!ffStrbufIgnCaseEqualS(&result->terminalProcessName, "stable") && //for WarpTerminal
|
||||
#else
|
||||
!ffStrbufIgnCaseEqualS(&result->terminalProcessName, "systemd") &&
|
||||
!ffStrbufIgnCaseEqualS(&result->terminalProcessName, "init") &&
|
||||
!ffStrbufIgnCaseEqualS(&result->terminalProcessName, "(init)") &&
|
||||
#endif
|
||||
|
||||
ffStrbufIgnCaseCompS(&result->terminalProcessName, "0") != 0
|
||||
) return;
|
||||
|
||||
@@ -193,11 +199,13 @@ static void getTerminalFromEnv(FFTerminalShellResult* result)
|
||||
if(getenv("SSH_CONNECTION") != NULL)
|
||||
term = getenv("SSH_TTY");
|
||||
|
||||
#ifdef __linux__
|
||||
//Windows Terminal
|
||||
if(!ffStrSet(term) && (
|
||||
getenv("WT_SESSION") != NULL ||
|
||||
getenv("WT_PROFILE_ID") != NULL
|
||||
)) term = "Windows Terminal";
|
||||
#endif
|
||||
|
||||
//Alacritty
|
||||
if(!ffStrSet(term) && (
|
||||
@@ -230,10 +238,8 @@ static void getTerminalFromEnv(FFTerminalShellResult* result)
|
||||
if(!ffStrSet(term))
|
||||
{
|
||||
//We are in WSL but not in Windows Terminal
|
||||
const FFHostResult* host = ffDetectHost();
|
||||
if(ffStrbufCompS(&host->productName, FF_HOST_PRODUCT_NAME_WSL) == 0 ||
|
||||
ffStrbufCompS(&host->productName, FF_HOST_PRODUCT_NAME_MSYS) == 0) //TODO better WSL or MSYS detection
|
||||
term = "conhost";
|
||||
if(getenv("WSL_DISTRO") != NULL || getenv("WSL_INTEROP") != NULL)
|
||||
term = "conhost";
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -365,6 +371,8 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance)
|
||||
ffStrbufInitS(&result.terminalPrettyName, "iTerm");
|
||||
else if(ffStrbufEqualS(&result.terminalProcessName, "Apple_Terminal"))
|
||||
ffStrbufInitS(&result.terminalPrettyName, "Apple Terminal");
|
||||
else if(ffStrbufEqualS(&result.terminalProcessName, "WarpTerminal"))
|
||||
ffStrbufInitS(&result.terminalPrettyName, "Warp");
|
||||
else if(strncmp(result.terminalExeName, result.terminalProcessName.chars, result.terminalProcessName.length) == 0) // if exeName starts with processName, print it. Otherwise print processName
|
||||
ffStrbufInitS(&result.terminalPrettyName, result.terminalExeName);
|
||||
else
|
||||
|
||||
@@ -189,6 +189,8 @@ static uint32_t getTerminalInfo(FFTerminalShellResult* result, uint32_t pid)
|
||||
ffStrbufSetS(&result->terminalPrettyName, "Visual Studio Code");
|
||||
else if(ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "explorer"))
|
||||
ffStrbufSetS(&result->terminalPrettyName, "Windows Explorer");
|
||||
else if(ffStrbufStartsWithIgnCaseS(&result->terminalPrettyName, "ConEmuC"))
|
||||
ffStrbufSetS(&result->terminalPrettyName, "ConEmu");
|
||||
|
||||
return ppid;
|
||||
}
|
||||
|
||||
@@ -4,38 +4,67 @@
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <Windows.h>
|
||||
|
||||
static inline void wrapRegCloseKey(HKEY* phKey)
|
||||
{
|
||||
if(*phKey)
|
||||
RegCloseKey(*phKey);
|
||||
}
|
||||
|
||||
bool ffDetectWmTheme(FFinstance* instance, FFstrbuf* themeOrError)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
HKEY hKey;
|
||||
if(RegOpenKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
|
||||
HKEY __attribute__((__cleanup__(wrapRegCloseKey))) hKey = NULL;
|
||||
if(RegOpenKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
||||
{
|
||||
ffStrbufAppendS(themeOrError, "RegOpenKeyExW() failed");
|
||||
int SystemUsesLightTheme = 1;
|
||||
DWORD bufSize = sizeof(SystemUsesLightTheme);
|
||||
|
||||
if(RegGetValueW(hKey, NULL, L"SystemUsesLightTheme", RRF_RT_DWORD, NULL, &SystemUsesLightTheme, &bufSize) != ERROR_SUCCESS)
|
||||
{
|
||||
ffStrbufAppendS(themeOrError, "RegGetValueW(SystemUsesLightTheme) failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
int AppsUsesLightTheme = 1;
|
||||
bufSize = sizeof(AppsUsesLightTheme);
|
||||
if(RegGetValueW(hKey, NULL, L"AppsUseLightTheme", RRF_RT_DWORD, NULL, &AppsUsesLightTheme, &bufSize) != ERROR_SUCCESS)
|
||||
{
|
||||
ffStrbufAppendS(themeOrError, "RegGetValueW(AppsUseLightTheme) failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
ffStrbufAppendF(themeOrError, "System - %s, Apps - %s", SystemUsesLightTheme ? "Light" : "Dark", AppsUsesLightTheme ? "Light" : "Dark");
|
||||
|
||||
return true;
|
||||
}
|
||||
else if(RegOpenKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD length = 0;
|
||||
if(RegGetValueA(hKey, NULL, "CurrentTheme", RRF_RT_REG_SZ, NULL, NULL, &length) != ERROR_SUCCESS)
|
||||
{
|
||||
ffStrbufAppendS(themeOrError, "RegGetValueA(CurrentTheme, NULL) failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
ffStrbufEnsureFree(themeOrError, length);
|
||||
if(RegGetValueA(hKey, NULL, "CurrentTheme", RRF_RT_REG_SZ, NULL, themeOrError->chars, &length) != ERROR_SUCCESS)
|
||||
{
|
||||
ffStrbufAppendS(themeOrError, "RegGetValueA(CurrentTheme) failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
themeOrError->length = length;
|
||||
ffStrbufSubstrBeforeLastC(themeOrError, '.');
|
||||
ffStrbufSubstrAfterLastC(themeOrError, '\\');
|
||||
if (isalpha(themeOrError->chars[0]))
|
||||
themeOrError->chars[0] = (char)toupper(themeOrError->chars[0]);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufAppendS(themeOrError, "Failed to find current theme");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
int SystemUsesLightTheme = 1;
|
||||
DWORD bufSize = sizeof(SystemUsesLightTheme);
|
||||
|
||||
if(RegQueryValueExW(hKey, L"SystemUsesLightTheme", NULL, NULL, (LPBYTE)&SystemUsesLightTheme, &bufSize) != ERROR_SUCCESS)
|
||||
{
|
||||
ffStrbufAppendS(themeOrError, "RegOpenKeyExW(SystemUsesLightTheme) failed");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
int AppsUsesLightTheme = 1;
|
||||
bufSize = sizeof(AppsUsesLightTheme);
|
||||
if(RegQueryValueExW(hKey, L"AppsUseLightTheme", NULL, NULL, (LPBYTE)&AppsUsesLightTheme, &bufSize) != ERROR_SUCCESS)
|
||||
{
|
||||
ffStrbufAppendS(themeOrError, "RegOpenKeyExW(AppsUseLightTheme) failed");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ffStrbufAppendF(themeOrError, "System - %s, Apps - %s", SystemUsesLightTheme ? "Light" : "Dark", AppsUsesLightTheme ? "Light" : "Dark");
|
||||
|
||||
exit:
|
||||
RegCloseKey(hKey);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -44,12 +44,6 @@ void ffPrintGPU(FFinstance* instance)
|
||||
if(ffPrintFromCache(instance, FF_GPU_MODULE_NAME, &instance->config.gpu, FF_GPU_NUM_FORMAT_ARGS))
|
||||
return;
|
||||
|
||||
if(ffStrbufCompS(&ffDetectHost()->productName, FF_HOST_PRODUCT_NAME_WSL) == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpu, "WSL doesn't expose senseful GPU names");
|
||||
return;
|
||||
}
|
||||
|
||||
const FFlist* gpus = ffDetectGPU(instance);
|
||||
|
||||
if(gpus->length == 0)
|
||||
|
||||
@@ -45,4 +45,8 @@ static inline void ffListSort(FFlist* list, int(*compar)(const void*, const void
|
||||
qsort(list->data, list->length, list->elementSize, compar);
|
||||
}
|
||||
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
#define FF_LIST_AUTO_DESTROY FFlist __attribute__((__cleanup__(ffListDestroy)))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -301,4 +301,9 @@ static inline FF_C_NODISCARD bool ffStrbufEndsWithIgnCase(const FFstrbuf* strbuf
|
||||
{
|
||||
return ffStrbufEndsWithIgnCaseNS(strbuf, end->length, end->chars);
|
||||
}
|
||||
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
#define FF_STRBUF_AUTO_DESTROY FFstrbuf __attribute__((__cleanup__(ffStrbufDestroy)))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
#import <AppKit/AppKit.h>
|
||||
#import <CoreData/CoreData.h>
|
||||
|
||||
bool ffOsascript(const char* input, FFstrbuf* result) {
|
||||
NSString* appleScript = [NSString stringWithUTF8String: input];
|
||||
NSAppleScript* script = [[NSAppleScript alloc] initWithSource:appleScript];
|
||||
bool ffOsascript(const char* input, FFstrbuf* result)
|
||||
{
|
||||
NSAppleScript* script = [NSAppleScript.alloc initWithSource:@(input)];
|
||||
NSDictionary* errInfo = nil;
|
||||
NSAppleEventDescriptor* descriptor = [script executeAndReturnError:&errInfo];
|
||||
if (errInfo)
|
||||
return false;
|
||||
|
||||
ffStrbufSetS(result, [[descriptor stringValue] cStringUsingEncoding:NSUTF8StringEncoding]);
|
||||
ffStrbufSetS(result, descriptor.stringValue.UTF8String);
|
||||
return true;
|
||||
}
|
||||
|
||||
+15
-13
@@ -27,20 +27,22 @@ static int detectVersion(struct utsname *name)
|
||||
|
||||
DWORD bufSize;
|
||||
|
||||
DWORD currentMajorVersionNumber;
|
||||
bufSize = sizeof(currentMajorVersionNumber);
|
||||
if(RegGetValueA(hKey, NULL, "CurrentMajorVersionNumber", RRF_RT_REG_DWORD, NULL, ¤tMajorVersionNumber, &bufSize) != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(hKey);
|
||||
return 1;
|
||||
}
|
||||
char currentVersion[32];
|
||||
|
||||
DWORD currentMinorVersionNumber;
|
||||
bufSize = sizeof(currentMinorVersionNumber);
|
||||
if(RegGetValueA(hKey, NULL, "CurrentMinorVersionNumber", RRF_RT_REG_DWORD, NULL, ¤tMinorVersionNumber, &bufSize) != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(hKey);
|
||||
return 1;
|
||||
DWORD currentMajorVersionNumber;
|
||||
DWORD currentMinorVersionNumber;
|
||||
bufSize = sizeof(currentMajorVersionNumber);
|
||||
if(RegGetValueW(hKey, NULL, L"CurrentMajorVersionNumber", RRF_RT_REG_DWORD, NULL, ¤tMajorVersionNumber, &bufSize) == ERROR_SUCCESS &&
|
||||
RegGetValueW(hKey, NULL, L"CurrentMinorVersionNumber", RRF_RT_REG_DWORD, NULL, ¤tMinorVersionNumber, &bufSize) == ERROR_SUCCESS
|
||||
)
|
||||
snprintf(currentVersion, sizeof(currentVersion), "%u.%u", (unsigned)currentMajorVersionNumber, (unsigned)currentMinorVersionNumber);
|
||||
else
|
||||
{
|
||||
bufSize = sizeof(currentVersion);
|
||||
if(RegGetValueA(hKey, NULL, "CurrentVersion", RRF_RT_REG_SZ, NULL, currentVersion, &bufSize) != ERROR_SUCCESS)
|
||||
strcpy(currentVersion, "0.0");
|
||||
}
|
||||
}
|
||||
|
||||
char currentBuildNumber[32];
|
||||
@@ -53,7 +55,7 @@ static int detectVersion(struct utsname *name)
|
||||
if(RegGetValueA(hKey, NULL, "UBR", RRF_RT_REG_DWORD, NULL, &ubr, &bufSize) != ERROR_SUCCESS || bufSize != sizeof(ubr))
|
||||
ubr = 0;
|
||||
|
||||
snprintf(name->release, sizeof(name->release), "%u.%u.%s.%u", (unsigned)currentMajorVersionNumber, (unsigned)currentMinorVersionNumber, currentBuildNumber, (unsigned)ubr);
|
||||
snprintf(name->release, sizeof(name->release), "%s.%s.%u", currentVersion, currentBuildNumber, (unsigned)ubr);
|
||||
|
||||
bufSize = sizeof(name->version);
|
||||
RegGetValueA(hKey, NULL, "DisplayVersion", RRF_RT_REG_SZ, NULL, name->version, &bufSize);
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// Include the necessary resources
|
||||
//
|
||||
#include <winver.h>
|
||||
#include <ntdef.h>
|
||||
|
||||
#ifdef RC_INVOKED
|
||||
|
||||
//
|
||||
// Set up debug information
|
||||
//
|
||||
#if DEBUG
|
||||
#define VER_DEBUG VS_FF_DEBUG
|
||||
#else
|
||||
#define VER_DEBUG 0
|
||||
#endif
|
||||
|
||||
// ------- version info -------------------------------------------------------
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,@PROJECT_VERSION_TWEAK_NUM@
|
||||
PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,@PROJECT_VERSION_TWEAK_NUM@
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
FILEFLAGS (VER_DEBUG|VS_FF_PRERELEASE)
|
||||
FILEOS VOS_NT
|
||||
FILETYPE VFT_APP
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "@PROJECT_HOMEPAGE_URL@"
|
||||
VALUE "FileDescription", "@PROJECT_DESCRIPTION@"
|
||||
VALUE "FileVersion", "@PROJECT_VERSION@@PROJECT_VERSION_TWEAK@"
|
||||
VALUE "InternalName", "@TARGET_NAME@.exe"
|
||||
VALUE "LegalCopyright", "@PROJECT_LICENSE@"
|
||||
VALUE "OriginalFilename", "@TARGET_NAME@.exe"
|
||||
VALUE "ProductName", "@PROJECT_NAME@"
|
||||
VALUE "ProductVersion", "@PROJECT_VERSION@@PROJECT_VERSION_TWEAK@"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0409,1252
|
||||
END
|
||||
END
|
||||
#endif
|
||||
@@ -128,7 +128,7 @@ FFWmiQuery::FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error)
|
||||
if (InitOnceExecuteOnce(&s_InitOnce, &InitHandleFunction, nullptr, (void**)&context) == FALSE)
|
||||
{
|
||||
if(error)
|
||||
ffStrbufInitS(error, context);
|
||||
ffStrbufAppendS(error, context);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,12 +23,15 @@ struct FFWmiRecord
|
||||
if(!ok) obj = nullptr;
|
||||
}
|
||||
FFWmiRecord(const FFWmiRecord&) = delete;
|
||||
FFWmiRecord(FFWmiRecord&& other) {
|
||||
obj = other.obj;
|
||||
other.obj = nullptr;
|
||||
}
|
||||
FFWmiRecord(FFWmiRecord&& other) { *this = (FFWmiRecord&&)other; }
|
||||
~FFWmiRecord() { if(obj) obj->Release(); }
|
||||
explicit operator bool() { return !!obj; }
|
||||
FFWmiRecord& operator =(FFWmiRecord&& other) {
|
||||
if(obj) obj->Release();
|
||||
obj = other.obj;
|
||||
other.obj = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool getString(const wchar_t* key, FFstrbuf* strbuf);
|
||||
bool getSigned(const wchar_t* key, int64_t* integer);
|
||||
@@ -43,13 +46,16 @@ struct FFWmiQuery
|
||||
FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error = nullptr);
|
||||
explicit FFWmiQuery(IEnumWbemClassObject* pEnumerator): pEnumerator(pEnumerator) {}
|
||||
FFWmiQuery(const FFWmiQuery& other) = delete;
|
||||
FFWmiQuery(FFWmiQuery&& other) {
|
||||
pEnumerator = other.pEnumerator;
|
||||
other.pEnumerator = nullptr;
|
||||
}
|
||||
FFWmiQuery(FFWmiQuery&& other) { *this = (FFWmiQuery&&)other; }
|
||||
~FFWmiQuery() { if(pEnumerator) pEnumerator->Release(); }
|
||||
|
||||
explicit operator bool() { return !!pEnumerator; }
|
||||
FFWmiQuery& operator =(FFWmiQuery&& other) {
|
||||
if(pEnumerator) pEnumerator->Release();
|
||||
pEnumerator = other.pEnumerator;
|
||||
other.pEnumerator = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FFWmiRecord next() {
|
||||
FFWmiRecord result(pEnumerator);
|
||||
|
||||
Reference in New Issue
Block a user