diff --git a/makefile b/makefile index ea9a56e..040ed31 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,5 @@ CFLAGS = -std=c99 -Wall -DNDEBUG -Ofast -ffast-math -fvisibility=hidden -fno-common -LIBS = -framework Carbon -framework Cocoa -framework CoreAudio -F/System/Library/PrivateFrameworks -framework SkyLight +LIBS = -framework Carbon -framework Cocoa -framework CoreAudio -F/System/Library/PrivateFrameworks -framework SkyLight -framework DisplayServices ODIR = bin SRC = src diff --git a/src/bar_item.c b/src/bar_item.c index 9deea83..fa23496 100644 --- a/src/bar_item.c +++ b/src/bar_item.c @@ -1000,6 +1000,10 @@ void bar_item_parse_subscribe_message(struct bar_item* bar_item, char* message, begin_receiving_volume_events(); } + if (event_flag & UPDATE_BRIGHTNESS_CHANGE) { + begin_receiving_brightness_events(); + } + bar_item->update_mask |= event_flag; if (!event_flag) { @@ -1007,6 +1011,5 @@ void bar_item_parse_subscribe_message(struct bar_item* bar_item, char* message, } event = get_token(&message); - } } diff --git a/src/bar_manager.c b/src/bar_manager.c index 17ed50d..030ecd6 100644 --- a/src/bar_manager.c +++ b/src/bar_manager.c @@ -745,6 +745,18 @@ void bar_manager_handle_volume_change(struct bar_manager* bar_manager, float vol env_vars_destroy(&env_vars); } +void bar_manager_handle_brightness_change(struct bar_manager* bar_manager, float brightness) { + struct env_vars env_vars; + env_vars_init(&env_vars); + char brightness_str[16]; + snprintf(brightness_str, 16, "%d", (int)(brightness*100. + 0.5)); + env_vars_set(&env_vars, string_copy("INFO"), string_copy(brightness_str)); + bar_manager_custom_events_trigger(bar_manager, + COMMAND_SUBSCRIBE_BRIGHTNESS_CHANGE, + &env_vars ); + env_vars_destroy(&env_vars); +} + void bar_manager_handle_front_app_switch(struct bar_manager* bar_manager, char* info) { struct env_vars env_vars; env_vars_init(&env_vars); diff --git a/src/bar_manager.h b/src/bar_manager.h index eedfccd..d598cbc 100644 --- a/src/bar_manager.h +++ b/src/bar_manager.h @@ -102,6 +102,7 @@ void bar_manager_handle_display_change(struct bar_manager* bar_manager); void bar_manager_handle_system_woke(struct bar_manager* bar_manager); void bar_manager_handle_system_will_sleep(struct bar_manager* bar_manager); void bar_manager_handle_volume_change(struct bar_manager* bar_manager, float volume); +void bar_manager_handle_brightness_change(struct bar_manager* bar_manager, float brightness); void bar_manager_custom_events_trigger(struct bar_manager* bar_manager, char* name, struct env_vars* env_vars); void bar_manager_destroy(struct bar_manager* bar_manager); diff --git a/src/custom_events.c b/src/custom_events.c index 6c943f1..43f6060 100644 --- a/src/custom_events.c +++ b/src/custom_events.c @@ -30,6 +30,7 @@ void custom_events_init(struct custom_events* custom_events) { custom_events_append(custom_events, string_copy(COMMAND_SUBSCRIBE_MOUSE_ENTERED_GLOBAL), NULL); custom_events_append(custom_events, string_copy(COMMAND_SUBSCRIBE_MOUSE_EXITED_GLOBAL), NULL); custom_events_append(custom_events, string_copy(COMMAND_SUBSCRIBE_VOLUME_CHANGE), NULL); + custom_events_append(custom_events, string_copy(COMMAND_SUBSCRIBE_BRIGHTNESS_CHANGE), NULL); } void custom_events_append(struct custom_events* custom_events, char* name, char* notification) { diff --git a/src/custom_events.h b/src/custom_events.h index 4940210..074d311 100644 --- a/src/custom_events.h +++ b/src/custom_events.h @@ -12,6 +12,7 @@ #define UPDATE_ENTERED_GLOBAL 1ULL << 8 #define UPDATE_EXITED_GLOBAL 1ULL << 9 #define UPDATE_VOLUME_CHANGE 1ULL << 10 +#define UPDATE_BRIGHTNESS_CHANGE 1ULL << 11 extern void* g_workspace_context; extern void workspace_create_custom_observer(void** context, char* name); diff --git a/src/display.c b/src/display.c index eb90a2d..d4c993b 100644 --- a/src/display.c +++ b/src/display.c @@ -3,8 +3,26 @@ extern int workspace_display_notch_height(uint32_t did); extern struct event_loop g_event_loop; extern int g_connection; +extern bool g_brightness_events; +float g_last_brightness = 0; +static void brightness_handler(void* notification_center, uint32_t did, void* name, const void* sender, CFDictionaryRef info) { + float* brightness = malloc(sizeof(float)); + memset(brightness, 0, sizeof(float)); + DisplayServicesGetBrightness(did, brightness); + if (g_last_brightness < *brightness - 1e-2 || g_last_brightness > *brightness + 1e-2) { + g_last_brightness = *brightness; + struct event *event = event_create(&g_event_loop, + BRIGHTNESS_CHANGED, + (void *) brightness); + + event_loop_post(&g_event_loop, event); + } else { + free(brightness); + } +} + static DISPLAY_EVENT_HANDLER(display_handler) { if (flags & kCGDisplayAddFlag) { struct event *event = event_create(&g_event_loop, @@ -12,12 +30,16 @@ static DISPLAY_EVENT_HANDLER(display_handler) { (void *)(intptr_t) did); event_loop_post(&g_event_loop, event); + if (g_brightness_events && DisplayServicesCanChangeBrightness(did)) + DisplayServicesRegisterForBrightnessChangeNotifications(did, did, (void*)brightness_handler); } else if (flags & kCGDisplayRemoveFlag) { struct event *event = event_create(&g_event_loop, DISPLAY_REMOVED, (void *)(intptr_t) did); event_loop_post(&g_event_loop, event); + if (g_brightness_events && DisplayServicesCanChangeBrightness(did)) + DisplayServicesUnregisterForBrightnessChangeNotifications(did, did); } else if (flags & kCGDisplayMovedFlag) { struct event *event = event_create(&g_event_loop, DISPLAY_MOVED, @@ -211,4 +233,16 @@ bool display_end() { == kCGErrorSuccess; } +void begin_receiving_brightness_events() { + if (g_brightness_events) return; + g_brightness_events = true; + uint32_t count; + uint32_t* result = display_active_display_list(&count); + for (int i = 0; i < count; i++) { + uint32_t did = *(result + i); + if (DisplayServicesCanChangeBrightness(did)) { + DisplayServicesRegisterForBrightnessChangeNotifications(did, did, (void*)brightness_handler); + } + } +} diff --git a/src/display.h b/src/display.h index 8d6e55d..f07bbca 100644 --- a/src/display.h +++ b/src/display.h @@ -6,6 +6,11 @@ #define DISPLAY_EVENT_HANDLER(name) void name(uint32_t did, CGDisplayChangeSummaryFlags flags, void *context) typedef DISPLAY_EVENT_HANDLER(display_callback); +extern CGError DisplayServicesRegisterForBrightnessChangeNotifications(uint32_t did, uint32_t passthrough, void* callback); +extern CGError DisplayServicesUnregisterForBrightnessChangeNotifications(uint32_t did, uint32_t passthrough); +extern CGError DisplayServicesGetBrightness(uint32_t did, float* brightness); +extern CGError DisplayServicesCanChangeBrightness(uint32_t did); + extern CFUUIDRef CGDisplayCreateUUIDFromDisplayID(uint32_t did); extern CFArrayRef SLSCopyManagedDisplays(int cid); extern uint64_t SLSManagedDisplayGetCurrentSpace(int cid, CFStringRef uuid); @@ -31,3 +36,5 @@ CGRect display_bounds(uint32_t did); uint64_t display_space_id(uint32_t did); uint64_t *display_space_list(uint32_t did, int *count); int display_arrangement(uint32_t did); + +void begin_receiving_brightness_events(); diff --git a/src/event.c b/src/event.c index 7511787..8ec2c5d 100644 --- a/src/event.c +++ b/src/event.c @@ -256,3 +256,9 @@ EVENT_CALLBACK(EVENT_HANDLER_VOLUME_CHANGED) { free(context); return EVENT_SUCCESS; } + +EVENT_CALLBACK(EVENT_HANDLER_BRIGHTNESS_CHANGED) { + bar_manager_handle_brightness_change(&g_bar_manager, *(float*)context); + free(context); + return EVENT_SUCCESS; +} diff --git a/src/event.h b/src/event.h index be9c66b..36462b5 100644 --- a/src/event.h +++ b/src/event.h @@ -30,6 +30,7 @@ EVENT_CALLBACK(EVENT_HANDLER_MOUSE_UP); EVENT_CALLBACK(EVENT_HANDLER_MOUSE_ENTERED); EVENT_CALLBACK(EVENT_HANDLER_MOUSE_EXITED); EVENT_CALLBACK(EVENT_HANDLER_VOLUME_CHANGED); +EVENT_CALLBACK(EVENT_HANDLER_BRIGHTNESS_CHANGED); EVENT_CALLBACK(EVENT_HANDLER_DISTRIBUTED_NOTIFICATION); #define EVENT_QUEUED 0x0 @@ -61,6 +62,7 @@ enum event_type { MOUSE_ENTERED, MOUSE_EXITED, VOLUME_CHANGED, + BRIGHTNESS_CHANGED, DISTRIBUTED_NOTIFICATION, EVENT_TYPE_COUNT @@ -86,6 +88,7 @@ static const char *event_type_str[] = { [MOUSE_ENTERED] = "mouse_entered", [MOUSE_EXITED] = "mouse_exited", [VOLUME_CHANGED] = "volume_changed", + [BRIGHTNESS_CHANGED] = "brightness_changed", [DISTRIBUTED_NOTIFICATION] = "distributed_notification", [EVENT_TYPE_COUNT] = "event_type_count" @@ -103,6 +106,7 @@ static event_callback *event_handler[] = { [MOUSE_ENTERED] = EVENT_HANDLER_MOUSE_ENTERED, [MOUSE_EXITED] = EVENT_HANDLER_MOUSE_EXITED, [VOLUME_CHANGED] = EVENT_HANDLER_VOLUME_CHANGED, + [BRIGHTNESS_CHANGED] = EVENT_HANDLER_BRIGHTNESS_CHANGED, [DISTRIBUTED_NOTIFICATION] = EVENT_HANDLER_DISTRIBUTED_NOTIFICATION, [MENU_BAR_HIDDEN_CHANGED] = EVENT_HANDLER_MENU_BAR_HIDDEN_CHANGED, diff --git a/src/misc/defines.h b/src/misc/defines.h index fc5942b..a278198 100644 --- a/src/misc/defines.h +++ b/src/misc/defines.h @@ -94,6 +94,7 @@ #define COMMAND_SUBSCRIBE_SYSTEM_WOKE "system_woke" #define COMMAND_SUBSCRIBE_SYSTEM_WILL_SLEEP "system_will_sleep" #define COMMAND_SUBSCRIBE_VOLUME_CHANGE "volume_change" +#define COMMAND_SUBSCRIBE_BRIGHTNESS_CHANGE "brightness_change" #define COMMAND_SUBSCRIBE_MOUSE_ENTERED "mouse.entered" #define COMMAND_SUBSCRIBE_MOUSE_EXITED "mouse.exited" #define COMMAND_SUBSCRIBE_MOUSE_CLICKED "mouse.clicked" diff --git a/src/sketchybar.m b/src/sketchybar.m index e3a83bd..8d90825 100644 --- a/src/sketchybar.m +++ b/src/sketchybar.m @@ -34,6 +34,7 @@ char g_config_file[4096]; char g_lock_file[MAXLEN]; bool g_verbose; bool g_volume_events; +bool g_brightness_events; static int client_send_message(int argc, char **argv) { if (argc <= 1) { @@ -151,6 +152,7 @@ static inline void init_misc_settings(void) { CGEnableEventStateCombining(false); g_connection = SLSMainConnectionID(); g_volume_events = false; + g_brightness_events = false; } #pragma clang diagnostic pop