initalize

This commit is contained in:
xenomxrph
2025-07-16 15:00:51 +02:00
commit 8d16baf6f1
40 changed files with 2353 additions and 0 deletions

1
sketchybar/bridge/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
bin

View File

@@ -0,0 +1,3 @@
all:
(cd network_load && $(MAKE)) >/dev/null
(cd menus && $(MAKE)) >/dev/null

View File

@@ -0,0 +1,5 @@
bin/menus: menus.c | bin
clang -std=c99 -O3 -F/System/Library/PrivateFrameworks/ -framework Carbon -framework SkyLight $< -o $@
bin:
mkdir bin

View File

@@ -0,0 +1,248 @@
#include <Carbon/Carbon.h>
void ax_init() {
const void *keys[] = { kAXTrustedCheckOptionPrompt };
const void *values[] = { kCFBooleanTrue };
CFDictionaryRef options;
options = CFDictionaryCreate(kCFAllocatorDefault,
keys,
values,
sizeof(keys) / sizeof(*keys),
&kCFCopyStringDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks );
bool trusted = AXIsProcessTrustedWithOptions(options);
CFRelease(options);
if (!trusted) exit(1);
}
void ax_perform_click(AXUIElementRef element) {
if (!element) return;
AXUIElementPerformAction(element, kAXCancelAction);
usleep(150000);
AXUIElementPerformAction(element, kAXPressAction);
}
CFStringRef ax_get_title(AXUIElementRef element) {
CFTypeRef title = NULL;
AXError error = AXUIElementCopyAttributeValue(element,
kAXTitleAttribute,
&title );
if (error != kAXErrorSuccess) return NULL;
return title;
}
void ax_select_menu_option(AXUIElementRef app, int id) {
AXUIElementRef menubars_ref = NULL;
CFArrayRef children_ref = NULL;
AXError error = AXUIElementCopyAttributeValue(app,
kAXMenuBarAttribute,
(CFTypeRef*)&menubars_ref);
if (error == kAXErrorSuccess) {
error = AXUIElementCopyAttributeValue(menubars_ref,
kAXVisibleChildrenAttribute,
(CFTypeRef*)&children_ref );
if (error == kAXErrorSuccess) {
uint32_t count = CFArrayGetCount(children_ref);
if (id < count) {
AXUIElementRef item = CFArrayGetValueAtIndex(children_ref, id);
ax_perform_click(item);
}
if (children_ref) CFRelease(children_ref);
}
if (menubars_ref) CFRelease(menubars_ref);
}
}
void ax_print_menu_options(AXUIElementRef app) {
AXUIElementRef menubars_ref = NULL;
CFTypeRef menubar = NULL;
CFArrayRef children_ref = NULL;
AXError error = AXUIElementCopyAttributeValue(app,
kAXMenuBarAttribute,
(CFTypeRef*)&menubars_ref);
if (error == kAXErrorSuccess) {
error = AXUIElementCopyAttributeValue(menubars_ref,
kAXVisibleChildrenAttribute,
(CFTypeRef*)&children_ref );
if (error == kAXErrorSuccess) {
uint32_t count = CFArrayGetCount(children_ref);
for (int i = 1; i < count; i++) {
AXUIElementRef item = CFArrayGetValueAtIndex(children_ref, i);
CFTypeRef title = ax_get_title(item);
if (title) {
uint32_t buffer_len = 2*CFStringGetLength(title);
char buffer[2*CFStringGetLength(title)];
CFStringGetCString(title, buffer, buffer_len, kCFStringEncodingUTF8);
printf("%s\n", buffer);
CFRelease(title);
}
}
}
if (menubars_ref) CFRelease(menubars_ref);
if (children_ref) CFRelease(children_ref);
}
}
AXUIElementRef ax_get_extra_menu_item(char* alias) {
pid_t pid = 0;
CGRect bounds = CGRectNull;
CFArrayRef window_list = CGWindowListCopyWindowInfo(kCGWindowListOptionAll,
kCGNullWindowID );
char owner_buffer[256];
char name_buffer[256];
char buffer[512];
int window_count = CFArrayGetCount(window_list);
for (int i = 0; i < window_count; ++i) {
CFDictionaryRef dictionary = CFArrayGetValueAtIndex(window_list, i);
if (!dictionary) continue;
CFStringRef owner_ref = CFDictionaryGetValue(dictionary,
kCGWindowOwnerName);
CFNumberRef owner_pid_ref = CFDictionaryGetValue(dictionary,
kCGWindowOwnerPID);
CFStringRef name_ref = CFDictionaryGetValue(dictionary, kCGWindowName);
CFNumberRef layer_ref = CFDictionaryGetValue(dictionary, kCGWindowLayer);
CFDictionaryRef bounds_ref = CFDictionaryGetValue(dictionary,
kCGWindowBounds);
if (!name_ref || !owner_ref || !owner_pid_ref || !layer_ref || !bounds_ref)
continue;
long long int layer = 0;
CFNumberGetValue(layer_ref, CFNumberGetType(layer_ref), &layer);
uint64_t owner_pid = 0;
CFNumberGetValue(owner_pid_ref,
CFNumberGetType(owner_pid_ref),
&owner_pid );
if (layer != 0x19) continue;
bounds = CGRectNull;
if (!CGRectMakeWithDictionaryRepresentation(bounds_ref, &bounds)) continue;
CFStringGetCString(owner_ref,
owner_buffer,
sizeof(owner_buffer),
kCFStringEncodingUTF8);
CFStringGetCString(name_ref,
name_buffer,
sizeof(name_buffer),
kCFStringEncodingUTF8);
snprintf(buffer, sizeof(buffer), "%s,%s", owner_buffer, name_buffer);
if (strcmp(buffer, alias) == 0) {
pid = owner_pid;
break;
}
}
CFRelease(window_list);
if (!pid) return NULL;
AXUIElementRef app = AXUIElementCreateApplication(pid);
if (!app) return NULL;
AXUIElementRef result = NULL;
CFTypeRef extras = NULL;
CFArrayRef children_ref = NULL;
AXError error = AXUIElementCopyAttributeValue(app,
kAXExtrasMenuBarAttribute,
&extras );
if (error == kAXErrorSuccess) {
error = AXUIElementCopyAttributeValue(extras,
kAXVisibleChildrenAttribute,
(CFTypeRef*)&children_ref );
if (error == kAXErrorSuccess) {
uint32_t count = CFArrayGetCount(children_ref);
for (uint32_t i = 0; i < count; i++) {
AXUIElementRef item = CFArrayGetValueAtIndex(children_ref, i);
CFTypeRef position_ref = NULL;
CFTypeRef size_ref = NULL;
AXUIElementCopyAttributeValue(item, kAXPositionAttribute,
&position_ref );
AXUIElementCopyAttributeValue(item, kAXSizeAttribute,
&size_ref );
if (!position_ref || !size_ref) continue;
CGPoint position = CGPointZero;
AXValueGetValue(position_ref, kAXValueCGPointType, &position);
CGSize size = CGSizeZero;
AXValueGetValue(size_ref, kAXValueCGSizeType, &size);
CFRelease(position_ref);
CFRelease(size_ref);
// The offset is exactly 8 on macOS Sonoma...
// printf("%f %f\n", position.x, bounds.origin.x);
if (error == kAXErrorSuccess
&& fabs(position.x - bounds.origin.x) <= 10) {
result = item;
break;
}
}
}
}
CFRelease(app);
return result;
}
extern int SLSMainConnectionID();
extern void SLSSetMenuBarVisibilityOverrideOnDisplay(int cid, int did, bool enabled);
extern void SLSSetMenuBarVisibilityOverrideOnDisplay(int cid, int did, bool enabled);
extern void SLSSetMenuBarInsetAndAlpha(int cid, double u1, double u2, float alpha);
void ax_select_menu_extra(char* alias) {
AXUIElementRef item = ax_get_extra_menu_item(alias);
if (!item) return;
SLSSetMenuBarInsetAndAlpha(SLSMainConnectionID(), 0, 1, 0.0);
SLSSetMenuBarVisibilityOverrideOnDisplay(SLSMainConnectionID(), 0, true);
SLSSetMenuBarInsetAndAlpha(SLSMainConnectionID(), 0, 1, 0.0);
ax_perform_click(item);
SLSSetMenuBarVisibilityOverrideOnDisplay(SLSMainConnectionID(), 0, false);
SLSSetMenuBarInsetAndAlpha(SLSMainConnectionID(), 0, 1, 1.0);
CFRelease(item);
}
extern void _SLPSGetFrontProcess(ProcessSerialNumber* psn);
extern void SLSGetConnectionIDForPSN(int cid, ProcessSerialNumber* psn, int* cid_out);
extern void SLSConnectionGetPID(int cid, pid_t* pid_out);
AXUIElementRef ax_get_front_app() {
ProcessSerialNumber psn;
_SLPSGetFrontProcess(&psn);
int target_cid;
SLSGetConnectionIDForPSN(SLSMainConnectionID(), &psn, &target_cid);
pid_t pid;
SLSConnectionGetPID(target_cid, &pid);
return AXUIElementCreateApplication(pid);
}
int main (int argc, char **argv) {
if (argc == 1) {
printf("Usage: %s [-l | -s id/alias ]\n", argv[0]);
exit(0);
}
ax_init();
if (strcmp(argv[1], "-l") == 0) {
AXUIElementRef app = ax_get_front_app();
if (!app) return 1;
ax_print_menu_options(app);
CFRelease(app);
} else if (argc == 3 && strcmp(argv[1], "-s") == 0) {
int id = 0;
if (sscanf(argv[2], "%d", &id) == 1) {
AXUIElementRef app = ax_get_front_app();
if (!app) return 1;
ax_select_menu_option(app, id);
CFRelease(app);
} else ax_select_menu_extra(argv[2]);
}
return 0;
}

View File

@@ -0,0 +1,5 @@
bin/network_load: network_load.c network_load.h ../sketchybar.h | bin
clang -std=c99 -O3 $< -o $@
bin:
mkdir bin

View File

@@ -0,0 +1,39 @@
#include "network_load.h"
#include "../sketchybar.h"
#include <unistd.h>
int main(int argc, char **argv) {
float update_freq;
if (argc < 4 || (sscanf(argv[3], "%f", &update_freq) != 1)) {
printf("Usage: %s \"<interface>\" \"<event-name>\" \"<event_freq>\"\n",
argv[0]);
exit(1);
}
alarm(0);
// Setup the event in sketchybar
char event_message[512];
snprintf(event_message, 512, "--add event '%s'", argv[2]);
sketchybar(event_message);
struct network network;
network_init(&network, argv[1]);
char trigger_message[512];
for (;;) {
// Acquire new info
network_update(&network);
// Prepare the event message
snprintf(trigger_message, 512,
"--trigger '%s' upload='%03d%s' download='%03d%s'", argv[2],
network.up, unit_str[network.up_unit], network.down,
unit_str[network.down_unit]);
// Trigger the event
sketchybar(trigger_message);
// Wait
usleep(update_freq * 1000000);
}
return 0;
}

View File

@@ -0,0 +1,93 @@
#include <math.h>
#include <net/if.h>
#include <net/if_mib.h>
#include <stdio.h>
#include <string.h>
#include <sys/select.h>
#include <sys/sysctl.h>
static char unit_str[3][6] = {
{" Bps"},
{"KBps"},
{"MBps"},
};
enum unit { UNIT_BPS, UNIT_KBPS, UNIT_MBPS };
struct network {
uint32_t row;
struct ifmibdata data;
struct timeval tv_nm1, tv_n, tv_delta;
int up;
int down;
enum unit up_unit, down_unit;
};
static inline void ifdata(uint32_t net_row, struct ifmibdata *data) {
static size_t size = sizeof(struct ifmibdata);
static int32_t data_option[] = {CTL_NET, PF_LINK, NETLINK_GENERIC,
IFMIB_IFDATA, 0, IFDATA_GENERAL};
data_option[4] = net_row;
sysctl(data_option, 6, data, &size, NULL, 0);
}
static inline void network_init(struct network *net, char *ifname) {
memset(net, 0, sizeof(struct network));
static int count_option[] = {CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_SYSTEM,
IFMIB_IFCOUNT};
uint32_t interface_count = 0;
size_t size = sizeof(uint32_t);
sysctl(count_option, 5, &interface_count, &size, NULL, 0);
for (int i = 0; i < interface_count; i++) {
ifdata(i, &net->data);
if (strcmp(net->data.ifmd_name, ifname) == 0) {
net->row = i;
break;
}
}
}
static inline void network_update(struct network *net) {
gettimeofday(&net->tv_n, NULL);
timersub(&net->tv_n, &net->tv_nm1, &net->tv_delta);
net->tv_nm1 = net->tv_n;
uint64_t ibytes_nm1 = net->data.ifmd_data.ifi_ibytes;
uint64_t obytes_nm1 = net->data.ifmd_data.ifi_obytes;
ifdata(net->row, &net->data);
double time_scale = (net->tv_delta.tv_sec + 1e-6 * net->tv_delta.tv_usec);
if (time_scale < 1e-6 || time_scale > 1e2)
return;
double delta_ibytes =
(double)(net->data.ifmd_data.ifi_ibytes - ibytes_nm1) / time_scale;
double delta_obytes =
(double)(net->data.ifmd_data.ifi_obytes - obytes_nm1) / time_scale;
double exponent_ibytes = log10(delta_ibytes);
double exponent_obytes = log10(delta_obytes);
if (exponent_ibytes < 3) {
net->down_unit = UNIT_BPS;
net->down = delta_ibytes;
} else if (exponent_ibytes < 6) {
net->down_unit = UNIT_KBPS;
net->down = delta_ibytes / 1000.0;
} else if (exponent_ibytes < 9) {
net->down_unit = UNIT_MBPS;
net->down = delta_ibytes / 1000000.0;
}
if (exponent_obytes < 3) {
net->up_unit = UNIT_BPS;
net->up = delta_obytes;
} else if (exponent_obytes < 6) {
net->up_unit = UNIT_KBPS;
net->up = delta_obytes / 1000.0;
} else if (exponent_obytes < 9) {
net->up_unit = UNIT_MBPS;
net->up = delta_obytes / 1000000.0;
}
}

View File

@@ -0,0 +1,124 @@
#pragma once
#include <bootstrap.h>
#include <mach/arm/kern_return.h>
#include <mach/mach.h>
#include <mach/mach_port.h>
#include <mach/message.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
typedef char *env;
#define MACH_HANDLER(name) void name(env env)
typedef MACH_HANDLER(mach_handler);
struct mach_message {
mach_msg_header_t header;
mach_msg_size_t msgh_descriptor_count;
mach_msg_ool_descriptor_t descriptor;
};
struct mach_buffer {
struct mach_message message;
mach_msg_trailer_t trailer;
};
static mach_port_t g_mach_port = 0;
static inline mach_port_t mach_get_bs_port() {
mach_port_name_t task = mach_task_self();
mach_port_t bs_port;
if (task_get_special_port(task, TASK_BOOTSTRAP_PORT, &bs_port) !=
KERN_SUCCESS) {
return 0;
}
char *name = getenv("BAR_NAME");
if (!name)
name = "sketchybar";
uint32_t lookup_len = 16 + strlen(name);
char buffer[lookup_len];
snprintf(buffer, lookup_len, "git.felix.%s", name);
mach_port_t port;
if (bootstrap_look_up(bs_port, buffer, &port) != KERN_SUCCESS)
return 0;
return port;
}
static inline bool mach_send_message(mach_port_t port, char *message,
uint32_t len) {
if (!message || !port) {
return false;
}
struct mach_message msg = {0};
msg.header.msgh_remote_port = port;
msg.header.msgh_local_port = 0;
msg.header.msgh_id = 0;
msg.header.msgh_bits =
MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND, 0,
MACH_MSGH_BITS_COMPLEX);
msg.header.msgh_size = sizeof(struct mach_message);
msg.msgh_descriptor_count = 1;
msg.descriptor.address = message;
msg.descriptor.size = len * sizeof(char);
msg.descriptor.copy = MACH_MSG_VIRTUAL_COPY;
msg.descriptor.deallocate = false;
msg.descriptor.type = MACH_MSG_OOL_DESCRIPTOR;
kern_return_t err =
mach_msg(&msg.header, MACH_SEND_MSG, sizeof(struct mach_message), 0,
MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
return err == KERN_SUCCESS;
}
static inline uint32_t format_message(char *message, char *formatted_message) {
// This is not actually robust, switch to stack based messaging.
char outer_quote = 0;
uint32_t caret = 0;
uint32_t message_length = strlen(message) + 1;
for (int i = 0; i < message_length; ++i) {
if (message[i] == '"' || message[i] == '\'') {
if (outer_quote && outer_quote == message[i])
outer_quote = 0;
else if (!outer_quote)
outer_quote = message[i];
continue;
}
formatted_message[caret] = message[i];
if (message[i] == ' ' && !outer_quote)
formatted_message[caret] = '\0';
caret++;
}
if (caret > 0 && formatted_message[caret] == '\0' &&
formatted_message[caret - 1] == '\0') {
caret--;
}
formatted_message[caret] = '\0';
return caret + 1;
}
static inline void sketchybar(char *message) {
char formatted_message[strlen(message) + 2];
uint32_t length = format_message(message, formatted_message);
if (!length)
return;
if (!g_mach_port)
g_mach_port = mach_get_bs_port();
if (!mach_send_message(g_mach_port, formatted_message, length)) {
g_mach_port = mach_get_bs_port();
if (!mach_send_message(g_mach_port, formatted_message, length)) {
// No sketchybar instance running, exit.
exit(0);
}
}
}