experimental: default item aliasing

This commit is contained in:
FelixKratz 2021-09-19 19:26:10 +02:00
parent 87d94d09fd
commit 86da5be578
9 changed files with 133 additions and 3 deletions

View file

@ -380,6 +380,27 @@ which you can freely configure to your liking by supplying a different script to
For performance reasons the space script is only run on change. For performance reasons the space script is only run on change.
I plan on increasing the available environment variables in scripting step by step but if you have a suggestion let me know in the issues. I plan on increasing the available environment variables in scripting step by step but if you have a suggestion let me know in the issues.
## Experimental Features
These are highly experimental features that need some work, but are included on HEAD anyways, because they do not interfere with
the rest of the bar.
### Default Menu Bar Item Alias
It is possible to create an alias for default menu bar items (such as MeetingBar, etc.) in sketchybar. This is still a bit janky though and needs some serious work
till it will be usable without headache.
Important: Autohiding of the default menu bar *must* be disabled, such that the bar is shown on screen before starting sketchybar. <br>
Sketchybar needs to be configured with *topmost* set to on, such that it draws on top of the default menu bar. <br>
I recommend turning off transparency of the bar and setting *margin* and *y_offset* to 0 and the *height* of the bar to at least 24, so that
sketchybar completely occludes the default bar. <br>
I also highly recommend setting a wallpaper on all spaces that makes the default menu bar items appear in either the light or the dark theme consitently.
It is now possible to create an alias of a default menu bar item with the following syntax:
```bash
sketchybar -m add alias <application_name> <position>
```
this operation requires screen capture permissions, which should be granted in the system preferences.
This will put the default item into sketchybar.
Aliases currently are not clickable.
## Credits ## Credits
yabai, yabai,
spacebar, spacebar,

View file

@ -1,6 +1,6 @@
FRAMEWORK_PATH = -F/System/Library/PrivateFrameworks FRAMEWORK_PATH = -F/System/Library/PrivateFrameworks
FRAMEWORK = -framework Carbon -framework Cocoa -framework SkyLight FRAMEWORK = -framework Carbon -framework Cocoa -framework SkyLight
BUILD_FLAGS = -std=c99 -Wall -DNDEBUG -O2 -fvisibility=hidden -mmacosx-version-min=10.13 BUILD_FLAGS = -std=c99 -Wall -DNDEBUG -Ofast -fvisibility=hidden -mmacosx-version-min=10.13
BUILD_PATH = ./bin BUILD_PATH = ./bin
SKETCHYBAR_SRC = ./src/manifest.m SKETCHYBAR_SRC = ./src/manifest.m
BINS = $(BUILD_PATH)/sketchybar BINS = $(BUILD_PATH)/sketchybar

61
src/alias.c Normal file
View file

@ -0,0 +1,61 @@
#include "alias.h"
#include "misc/helpers.h"
#include <string.h>
void alias_init(struct alias* alias, char* name) {
alias->using_light_colors = true;
alias->name = name;
alias->wid = 0;
alias->image_ref = NULL;
alias_update_image(alias);
}
void alias_find_window(struct alias* alias) {
CFArrayRef window_list = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
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);
CFStringRef name_ref = CFDictionaryGetValue(dictionary, kCGWindowName);
if (!name_ref) continue;
if (!owner_ref) continue;
CFNumberRef layer_ref = CFDictionaryGetValue(dictionary, kCGWindowLayer);
if (!layer_ref) continue;
uint64_t layer = 0;
CFNumberGetValue(layer_ref, CFNumberGetType(layer_ref), &layer);
if (layer != MENUBAR_LAYER) continue;
CFNumberRef window_id_ref = CFDictionaryGetValue(dictionary, kCGWindowNumber);
if (!window_id_ref) continue;
CGWindowID window_id = 0;
CFNumberGetValue(window_id_ref, CFNumberGetType(window_id_ref), &window_id);
char* owner = cfstring_copy(owner_ref);
char* name = cfstring_copy(name_ref);
if (strcmp(alias->name, owner) != 0) { free(owner); free(name); continue; }
alias->wid = window_id;
free(owner);
free(name);
CFRelease(window_list);
return;
}
alias->wid = 0;
CFRelease(window_list);
}
bool alias_update_image(struct alias* alias) {
if (alias->wid == 0) alias_find_window(alias);
if (alias->wid == 0) { alias->image_ref = NULL; return false; }
if (alias->image_ref) CFRelease(alias->image_ref);
alias->image_ref = CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow,
alias->wid, kCGWindowImageBestResolution);
if (!alias->image_ref) return false;
alias->size.x = CGImageGetWidth(alias->image_ref);
alias->size.y = CGImageGetHeight(alias->image_ref);
return true;
}

18
src/alias.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef ALIAS_H
#define ALIAS_H
#define MENUBAR_LAYER 0x19
struct alias {
bool using_light_colors;
char* name;
uint32_t wid;
CGImageRef image_ref;
CGPoint size;
};
void alias_init(struct alias* alias, char* name);
bool alias_update_image(struct alias* alias);
void alias_find_window(struct alias* alias);
#endif

View file

@ -154,6 +154,12 @@ void bar_draw_item_background(struct bar* bar, struct bar_item* bar_item, uint32
draw_rect(bar->context, draw_region, &bar_item->background_color, bar_item->background_corner_radius, bar_item->background_border_width, &bar_item->background_border_color, false); draw_rect(bar->context, draw_region, &bar_item->background_color, bar_item->background_corner_radius, bar_item->background_border_width, &bar_item->background_border_color, false);
} }
void bar_draw_alias(struct bar* bar, struct bar_item* bar_item, uint32_t x) {
if (!bar_item->has_alias || !bar_item->alias.image_ref) return;
CGRect bounds = {{x, (bar->frame.size.height - bar_item->alias.size.y) / 2},{bar_item->alias.size.x, bar_item->alias.size.y}};
CGContextDrawImage(bar->context, bounds, bar_item->alias.image_ref);
}
void bar_redraw(struct bar* bar) { void bar_redraw(struct bar* bar) {
uint32_t did = bar->adid; uint32_t did = bar->adid;
uint32_t sid = bar->sid; uint32_t sid = bar->sid;
@ -172,6 +178,7 @@ void bar_redraw(struct bar* bar) {
if (!bar_item->drawing) continue; if (!bar_item->drawing) continue;
if (bar_item->associated_display > 0 && !(bar_item->associated_display & (1 << did))) continue; if (bar_item->associated_display > 0 && !(bar_item->associated_display & (1 << did))) continue;
if (bar_item->associated_space > 0 && !(bar_item->associated_space & (1 << sid)) && (bar_item->type != BAR_COMPONENT_SPACE)) continue; if (bar_item->associated_space > 0 && !(bar_item->associated_space & (1 << sid)) && (bar_item->type != BAR_COMPONENT_SPACE)) continue;
if (bar_item->has_alias) alias_update_image(&bar_item->alias);
struct bar_line* label = &bar_item->label_line; struct bar_line* label = &bar_item->label_line;
struct bar_line* icon = &bar_item->icon_line; struct bar_line* icon = &bar_item->icon_line;
CGPoint icon_position = bar_align_line(bar, icon, ALIGN_CENTER, ALIGN_CENTER); CGPoint icon_position = bar_align_line(bar, icon, ALIGN_CENTER, ALIGN_CENTER);
@ -190,6 +197,9 @@ void bar_redraw(struct bar* bar) {
if (!bar_item->nospace) if (!bar_item->nospace)
bar_left_final_item_x += bar_item->graph_data.graph_width; bar_left_final_item_x += bar_item->graph_data.graph_width;
} }
if (bar_item->has_alias) {
bar_left_final_item_x += bar_item->alias.size.x;
}
} }
else if (bar_item->position == BAR_POSITION_RIGHT) { else if (bar_item->position == BAR_POSITION_RIGHT) {
label_position.x = bar_right_first_item_x - label->bounds.size.width - bar_item->label_spacing_right; label_position.x = bar_right_first_item_x - label->bounds.size.width - bar_item->label_spacing_right;
@ -202,6 +212,10 @@ void bar_redraw(struct bar* bar) {
graph_rtl = true; graph_rtl = true;
if (!bar_item->nospace) if (!bar_item->nospace)
bar_right_first_item_x -= bar_item->graph_data.graph_width; bar_right_first_item_x -= bar_item->graph_data.graph_width;
}
if (bar_item->has_alias) {
icon_position.x -= bar_item->alias.size.x;
bar_right_first_item_x -= bar_item->alias.size.x;
} }
} }
else if (bar_item->position == BAR_POSITION_CENTER) { else if (bar_item->position == BAR_POSITION_CENTER) {
@ -215,6 +229,9 @@ void bar_redraw(struct bar* bar) {
if (!bar_item->nospace) if (!bar_item->nospace)
bar_center_first_item_x += bar_item->graph_data.graph_width; bar_center_first_item_x += bar_item->graph_data.graph_width;
} }
if (bar_item->has_alias) {
bar_center_first_item_x += bar_item->alias.size.x;
}
} }
bar_item->label_line.bounds.origin = label_position; bar_item->label_line.bounds.origin = label_position;
bar_item->icon_line.bounds.origin = icon_position; bar_item->icon_line.bounds.origin = icon_position;
@ -223,6 +240,7 @@ void bar_redraw(struct bar* bar) {
bar_draw_item_background(bar, bar_item, sid); bar_draw_item_background(bar, bar_item, sid);
bar_draw_line(bar, icon, icon_position.x, icon_position.y); bar_draw_line(bar, icon, icon_position.x, icon_position.y);
bar_draw_alias(bar, bar_item, icon_position.x);
bar_draw_line(bar, label, label_position.x, label_position.y); bar_draw_line(bar, label, label_position.x, label_position.y);
bar_draw_graph(bar, bar_item, graph_x, graph_rtl); bar_draw_graph(bar, bar_item, graph_x, graph_rtl);
} }
@ -243,8 +261,8 @@ void bar_create_frame(struct bar *bar, CFTypeRef *frame_region) {
if (0 == strcmp(g_bar_manager.position, BAR_POSITION_BOTTOM)) { if (0 == strcmp(g_bar_manager.position, BAR_POSITION_BOTTOM)) {
origin.y = CGRectGetMaxY(bounds) - g_bar_manager.height - 2*g_bar_manager.y_offset; origin.y = CGRectGetMaxY(bounds) - g_bar_manager.height - 2*g_bar_manager.y_offset;
} else if (display_menu_bar_visible()) { } else if (display_menu_bar_visible()) {
CGRect menu = display_menu_bar_rect(bar->did); //CGRect menu = display_menu_bar_rect(bar->did);
origin.y += menu.size.height; //origin.y += menu.size.height;
} }
bar->frame = (CGRect) {{0, 0},{bounds.size.width, g_bar_manager.height}}; bar->frame = (CGRect) {{0, 0},{bounds.size.width, g_bar_manager.height}};

View file

@ -75,6 +75,7 @@ void bar_item_init(struct bar_item* bar_item, struct bar_item* default_item) {
bar_item->background_corner_radius = 0; bar_item->background_corner_radius = 0;
bar_item->background_border_width = 0; bar_item->background_border_width = 0;
bar_item->bounding_rects = NULL; bar_item->bounding_rects = NULL;
bar_item->has_alias = false;
if (default_item) bar_item_inherit_from_item(bar_item, default_item); if (default_item) bar_item_inherit_from_item(bar_item, default_item);

View file

@ -5,6 +5,7 @@
#define BAR_ITEM 'i' #define BAR_ITEM 'i'
#define BAR_COMPONENT_GRAPH 'g' #define BAR_COMPONENT_GRAPH 'g'
#define BAR_COMPONENT_SPACE 's' #define BAR_COMPONENT_SPACE 's'
#define BAR_COMPONENT_ALIAS 'a'
#define BAR_PLUGIN 'p' #define BAR_PLUGIN 'p'
#define BAR_POSITION_LEFT 'l' #define BAR_POSITION_LEFT 'l'
@ -78,6 +79,10 @@ struct bar_item {
bool has_graph; bool has_graph;
struct graph_data graph_data; struct graph_data graph_data;
// Alias Data
bool has_alias;
struct alias alias;
// Update Events // Update Events
uint32_t update_mask; uint32_t update_mask;

View file

@ -26,6 +26,7 @@
#include "display.h" #include "display.h"
#include "bar.h" #include "bar.h"
#include "graph_data.h" #include "graph_data.h"
#include "alias.h"
#include "bar_item.h" #include "bar_item.h"
#include "custom_events.h" #include "custom_events.h"
#include "bar_manager.h" #include "bar_manager.h"
@ -38,6 +39,7 @@
#include "display.c" #include "display.c"
#include "bar.c" #include "bar.c"
#include "graph_data.c" #include "graph_data.c"
#include "alias.c"
#include "bar_item.c" #include "bar_item.c"
#include "custom_events.c" #include "custom_events.c"
#include "bar_manager.c" #include "bar_manager.c"

View file

@ -314,6 +314,10 @@ static void handle_domain_add(FILE* rsp, struct token domain, char* message) {
bar_item_set_script(bar_item, string_copy("if [ \"$SELECTED\" = \"true\" ]; then sketchybar -m set $NAME icon_highlight on; else sketchybar -m set $NAME icon_highlight off; fi")); bar_item_set_script(bar_item, string_copy("if [ \"$SELECTED\" = \"true\" ]; then sketchybar -m set $NAME icon_highlight on; else sketchybar -m set $NAME icon_highlight off; fi"));
bar_item->update_mask |= UPDATE_SPACE_CHANGE; bar_item->update_mask |= UPDATE_SPACE_CHANGE;
} }
else if (bar_item->type == BAR_COMPONENT_ALIAS) {
alias_init(&bar_item->alias, token_to_string(name));
bar_item->has_alias = true;
}
} else if (token_equals(command, COMMAND_ADD_PLUGIN)) { } else if (token_equals(command, COMMAND_ADD_PLUGIN)) {
struct token identifier = get_token(&message); struct token identifier = get_token(&message);
name = get_token(&message); name = get_token(&message);