further syntax rework and update guide

This commit is contained in:
FelixKratz 2021-10-21 23:32:44 +02:00
parent 960cdc45f4
commit 8daecea1b3
8 changed files with 371 additions and 388 deletions

408
README.md
View file

@ -111,35 +111,10 @@ brew tap homebrew/cask-fonts
brew install --cask font-hack-nerd-font
```
## Configuration
Below is a list of all possible commands you can currently use to configure the bar in the configuration file located in *~/.config/sketchybar/sketchybarrc*
or directly from a command line
### Note on batching configuration commands
It is possible to batch commands together into a single call to sketchybar, this can be helpful to
keep the configuration file a bit cleaner and also to reduce startup times.
There always is a *standalone* version of a command and a *batch* version of the same command, with the
difference being, that all *batch* commands can be joined into a single call, for example:
## Global configuration of the bar
For an example configuration see the supplied default *sketchybarrc*.
```bash
sketchybar -m bar position top
sketchybar -m add item demo left
sketchybar -m set demo label Hello
sketchybar -m subscribe demo system_woke
```
turns into:
```bash
sketchybar -m batch --bar position=top \
--add item demo left \
--set demo label=Hello \
--subscribe demo system_woke
```
### Global configuration of the bar
```bash
sketchybar -m bar <setting> <value>
```
or when you want to batch configurations:
```bash
sketchybar -m batch --bar <setting>=<value> ... <setting>=<value>
sketchybar -m --bar <setting>=<value> ... <setting>=<value>
```
where the settings currently are:
@ -159,53 +134,34 @@ where the settings currently are:
* *topmost*: draws sketchybar on top of *everything* (even the default menu bar) (*on*, *off*, *toggle*, default: *off*)
* *font_smoothing*: wheter fonts should be smoothened (*on*, *off*, *toggle*, default: *off*)
### Adding a simple menubar item (items will appear in the bar in the order they are added)
## Items and their properties
Items are the main building blocks of sketchybar and can be configured in a number of ways. Items have the following basic structure: <br>
<img src="images/bar_item.png" width="300"> <br>
### Adding items to sketchybar
```bash
sketchybar -m add item <name> <position> [optional: <modifier>]
```
or with command batching:
```bash
sketchybar -m batch --add item <name> <position> [optional: <modifier>]
sketchybar -m --add item <name> <position>
```
where the *name* should not contain whitespaces, it can be used to further configure the item, which is covered later.
The *position* is the placement in the bar and can be either *left*, *right* or *center*.
The list of modifiers for item creation is short currently:
* *nospace*: This item reserves no space in the bar and the next item starts exactly where this item starts (good for stacked widgets) (DEPRECATED on HEAD, use *width* property)
The *position* is the placement in the bar and can be either *left*, *right* or *center*. The items will appear in the bar in the ordered
in which they are added.
### Adding a component
### Changing item properties
```bash
sketchybar -m add component <type> <name> <position> [optional: <modifier>]
```
or for batching of commands:
```bash
sketchybar -m batch --add component <type> <name> <position> [optional: <modifier>]
```
Components are essentially items, but with special properties.
Currently there are the component *types*:
* ~~*title*: Showing the current window title,~~ (DEPRECATED, see [this](https://github.com/FelixKratz/SketchyBar/discussions/12#discussioncomment-1215932))
* *graph*: showing a graph,
* *space*: representing a mission control space
* *alias*: a default menu bar item (for details see the experimental section)
* *bracket*: brackets together other items (for details see the experimental section)
### Changing the properties of an item
```bash
sketchybar -m set <name> <property> <value>
```
here batching is also possible with:
```bash
sketchybar -m batch --set <name> <property>=<value> ... <property>=<value>
sketchybar -m --set <name> <property>=<value> ... <property>=<value>
```
where the *name* is used to target the item with this name.
An item always has the following structure in the bar: <br>
<img src="images/bar_item.png" width="300"> <br>
background_padding_left|-icon_padding_left-|-icon-|-icon_padding_right-|-label_padding_left-|-label-|-label_padding_right-|background_padding_right <br>
A list of properties available to the *set* command is listed below (components might have additional properties, see the respective component section for them):
A list of properties available to the *set* command is listed below:
Geometry Properties:
* *position*: Overrides the position set in the *add* command (*left*, *right*, *center*)
* *associated_space*: on which space to show this item (can be multiple, not specifying anything will show item on all spaces)
* *associated_display*: on which displays to show this item (can be multiple, not specifying anything will show item on all displays)
* *width*: overrides the width of the item (useful for items which frequently change in width and thus move all other items) (values: width in points and *dynamic*)
* *y_offset*: the vertical offset of this item (default: 0)
Icon properties:
* *icon*: the icon of the item
* *icon.font*: the font for the icon
* *icon.color*: the color of the icon
@ -213,6 +169,8 @@ A list of properties available to the *set* command is listed below:
* *icon.padding_left*: left padding of icon (default: 0)
* *icon.padding_right*: right padding of icon (default: 0)
* *icon.highlight*: wether the icon is highlighted with the *icon_highlight_color* (values: *on*, *off*, *toggle*, default: *off*)
Label properties:
* *label*: the label of the item
* *label.font*: the font for the label
* *label.color*: the color of the label
@ -220,6 +178,8 @@ A list of properties available to the *set* command is listed below:
* *label.padding_left*: left padding of label (default: 0)
* *label.padding_right*: right padding of label (default: 0)
* *label.highlight*: wether the label is highlighted with the *label_highlight_color* (values: *on*, *off*, *toggle*, default: *off*)
Background properties:
* *background.drawing*: wether the item should draw a background (values: *on*, *off*, *toggle*, default: *off*)
* *background.color*: draws a rectangular background for this item in the given color (this automatically activates *draws_background*)
* *background.height*: the height of the background, the background will always be centered vertically around the center of the item
@ -228,90 +188,191 @@ A list of properties available to the *set* command is listed below:
* *background.border_width*: the border width of the items background (default: 0)
* *background.padding_left*: the left padding applied around the background of the item (default: 0)
* *background.padding_right*: the right padding applied around the background of the item (default: 0)
* *width*: overrides the width of the item (useful for items which frequently change in width and thus move all other items) (values: width in points and *dynamic*) (HEAD only)
* *y_offset*: the vertical offset of this item (default: 0)
* *graph.color*: color of the associated graph
* *graph.fill_color*: optional property to override the automatically calculated fill color of the graph
* *graph.line_width*: sets the line width of the associated graph
Scripting properties:
* *update_freq*: time in seconds between script executions
* *script*: a script to run every *update_freq* seconds
* *click_script*: script to run when left clicking on item (Note: This is also possible via the *mouse_clicked* event, see #subscribing-items-to-system-events-for-their-script-execution)
* *cache_scripts*: If the scripts should be cached in RAM or read from disc every time (values: *on*, *off*, *toggle*, default: *off*)
* *updates*: If and when the item updates e.g. via script execution (values: *on*, *off*, *toggle*, *when_shown*, default: *on*)
Drawing properties:
* *drawing*: If the item should be drawn into the bar (values: *on*, *off*, *toggle*, default: *on*)
* *lazy*: Changes do not trigger a redraw of the bar, item is refreshed when the bar is redrawn anyways (values: *on*, *off*, *toggle*, default: *off*)
### Changing the default values for all further items
It is possible to change the *defaults* at every point in the configuration. All item created *after* changing the defaults will
inherit these properties from the default item.
```bash
sketchybar -m default <property> <value>
sketchybar -m --default <property>=<value> ... <property>=<value>
```
batching is again possible via:
```bash
sketchybar -m batch --default <property>=<value> ... <property>=<value>
```
this currently works for the properties:
* *label.font*
* *label.color*
* *label.highlight_color*
* *label.padding_left*
* *label.padding_right*
* *icon.font*
* *icon.color*
* *icon.highlight_color*
* *icon.padding_left*
* *icon.padding_right*
* *background.drawing*
* *background.height*
* *background.color*
* *background.border_color*
* *background.corner_radius*
* *background.border_width*
* *y_offset*
* *update_freq*
* *script* (HEAD only)
* *click_script* (HEAD only)
* *cache_scripts*
* *updates*
* *drawing*
* *lazy*
this works for all item properties.
It is also possible to reset the defaults via the command
```bash
sketchybar -m default reset
sketchybar -m --default reset
```
### Subscribing items to system events for their script execution
## Components -- Special Items with special properties
Components are essentially items, but with special properties.
Currently there are the components (more details in the corresponding sections below):
* *graph*: showing a graph,
* *space*: representing a mission control space
* *bracket*: brackets together other items
* *alias*: a default menu bar item
### Data Graph -- Draws an arbitrary graph into the bar
```bash
sketchybar -m --add graph <name> <position>
```
Additional graph properties:
* *graph.color*: color of the associated graph
* *graph.fill_color*: optional property to override the automatically calculated fill color of the graph
* *graph.line_width*: sets the line width of the associated graph
Push data points into the graph via:
```bash
sketchybar -m --push <name> <data point>
```
### Space -- Associate mission control spaces with an item
```bash
sketchybar -m --add space <name> <position>
```
The space component overrides the definition of the following properties and they must be set to correctly associate a mission control space with this item:
* *associated_space*: Which space this item represents
* *associated_display*: On which display the *associated_space* is shown.
The space component has additional variables available in *scripts*:
```bash
$SELECTED
$SID
$DID
```
where *$SELECTED* has the value *true* if the associated space is selected and *false* if the selected space is not selected, while
*$SID* holds the space id and *$DID* the display id.
By default the space component invokes the following script:
```bash
if [ "$SELECTED" = "true" ]; then
sketchybar -m --set $NAME icon.highlight=on
else
sketchybar -m --set $NAME icon.highlight=off
fi
```
which you can freely configure to your liking by supplying a different script to the space component:
```bash
sketchybar -m --set <name> script=<path to script>
```
For performance reasons the space script is only run on change.
### Item Bracket -- Group Items in e.g. colored sections
It is possible to bracket together items via the command (see [this](https://github.com/FelixKratz/SketchyBar/discussions/12#discussioncomment-1455842) discussion for an example):
```bash
sketchybar -m --add bracket <name> <first item name> ... <n-th item name>
```
The first item must always be the one listed earliest in the config. It is now possible to
set properties for the bracket, just as for any item or component. Brackets currently only support all background features.
E.g., if I wanted a colored background around *all* my space components (which are named *code*, *writing*, *reading* and *entertainment*) I would set it up like this:
```bash
sketchybar -m --add bracket primary_spaces code \
writing \
reading \
entertainment \
\
--set primary_spaces background.color=0xffffffff \
background.corner_radius=4 \
background.height=20
```
this draws a white background below all my space components. I plan to expand the capability of item brackets significantly in the future.
### Item Alias -- Mirror items of the original macOS status bar into sketchybar
It is possible to create an alias for default menu bar items (such as MeetingBar, etc.) in sketchybar. The default menu bar can be set to autohide and this should still work.
Important: <br>
I 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 but can be modified with all the options available for simple items.
The command can be overloaded by providing a *window_owner* and a *window_name*
```bash
sketchybar -m --add alias <window_owner>,<window_name> <position>
```
this way the default system items can also be slurped into sketchybar, e.g.:
Owner: "Control Center", Name: Bluetooth <br>
Owner: "Control Center", Name: WiFi <br>
Or the individual widgets of [Stats](https://github.com/exelban/stats):<br>
Owner: Stats Name: CPU_Mini<br>
etc...<br>
All further default menu items currently available on your system can be found via the command:
```bash
sketchybar -m --query default_menu_items
```
This pushes the data point into the graph with name *name*.
## Batching of configuration commands
It is possible to batch commands together into a single call to sketchybar, this can be helpful to
keep the configuration file a bit cleaner and also to reduce startup times.
Assume 5 individual configuration calls to sketchybar:
```bash
sketchybar -m --bar position=top
sketchybar -m --bar margin=5
sketchybar -m --add item demo left
sketchybar -m --set demo label=Hello
sketchybar -m --subscribe demo system_woke
```
after each configuration command the bar is redrawn (if needed), thus it is more perfomant to append these calls into a single command like so:
```bash
sketchybar -m --bar position=top \
margin=5 \
--add item demo left \
--set demo label=Hello \
--subscribe demo system_woke
```
The backslash at the end of the first 4 lines is the default bash way to join lines together and should not be followed by a whitespace.
## Events and Scripting
Any item can *subscribe* to arbitrary *events*, when the *event* happens, all items subscribed to the *event* will execute their *script*.
This can be used to create more reactive and performant items which react to events rather than polling for a change.
```bash
sketchybar -m subscribe <name> <event> ... <event>
```
the batching command is very similar:
```bash
sketchybar -m batch --subscribe <name> <event> ... <event>
sketchybar -m --subscribe <name> <event> ... <event>
```
where the events are:
* *front_app_switched*: when frontmost application changes (not triggered if a different app of the same window is focused)
* *front_app_switched*: when the frontmost application changes (not triggered if a different app of the same window is focused)
* *space_change*: when the space is changed
* *display_change*: when the display is changed
* *system_woke*: when the system has awaken from sleep
* *mouse_entered*: when the mouse enters over an item (HEAD only)
* *mouse_exited*: when the mouse leaves an item (HEAD only)
* *mouse_clicked*: when an item is clicked (HEAD only)
* *mouse_entered*: when the mouse enters over an item
* *mouse_exited*: when the mouse leaves an item
* *mouse_clicked*: when an item is clicked
HEAD only: <br>
When an item is subscribed to these events the *script* is run and it gets passed the *$SENDER* variable, which holds exactly the above names, to distinguish between the different events.
It is thus possible to have a script that reacts to each event differently e.g. via a switch for the *$SENDER* variable in the *script*. I will soon create an example an link it here.
Alternatively a fixed *update_freq* can be *--set*, such that the event is routinely run to poll for change.
When an item invokes a script, the script has access to some environment variables, such as:
```bash
$NAME
$SENDER
```
Where *$NAME* is the name of the item that has invoked the script and *$SENDER* is the reason why the script is executed.
### Creating custom events
This allows to define events which are triggered by a different application (see Trigger custom events). Items can also subscribe to these events for their script execution.
```bash
sketchybar -m add event <name> [optional: <NSDistributedNotificationName>]
```
and the batch version of this:
```bash
sketchybar -m batch --add event <name> [optional: <NSDistributedNotificationName>]
sketchybar -m --add event <name> [optional: <NSDistributedNotificationName>]
```
Optional: You can subscribe to the notifications sent to the NSDistributedNotificationCenter e.g.
the notification Spotify sends on track change: "com.spotify.client.PlaybackStateChanged" [example](https://github.com/FelixKratz/SketchyBar/discussions/12#discussioncomment-1455842), or the
@ -321,136 +382,45 @@ to create more responsive items.
### Triggering custom events
This triggers a custom event that has been added before
```bash
sketchybar -m trigger <event>
sketchybar -m --trigger <event>
```
This could be used to link the powerful event system of yabai to sketchybar by triggering the custom action via a yabai event.
### Supplying data for graphs
```bash
sketchybar -m push <name> <data>
```
This pushes the data point into the graph with name *name*.
### Forcing all shell scripts to run and the bar to refresh
```bash
sketchybar -m update
sketchybar -m --update
```
### Completely remove an item
```bash
sketchybar -m remove item <name>
```
This also works for components, just reference it by name.
## Querying
*SketchyBar* can be queried for information about a number of things.
### Bar Properties
Information about the bar can be queried via:
```bash
sketchybar -m query bar
sketchybar -m --query bar
```
The output is a json structure containing relevant information about the configuration settings of the bar.
### Item Properties
Information about an item can be queried via:
```bash
sketchybar -m query item <name>
sketchybar -m --query item <name>
```
The output is a json structure containing relevant information about the configuration of the item.
### Default Properties
Information about the current defaults.
```bash
sketchybar -m query defaults
sketchybar -m --query defaults
```
## Scripting
The bar supports scripts where ever possible to make it as customizable and versatile as possible.
When an item invokes a script, the script has access to some environment variables, such as:
```bash
$NAME
$SENDER (HEAD only)
```
Where *$NAME* is the name of the item that has invoked the script and *$SENDER* is the reason why the script is executed ($SENDER only on HEAD).
The space component has additional variables:
```bash
$SELECTED
$SID
$DID
```
where $SELECTED has the value *true* if the associated space is selected and *false* if the selected space is not selected, while
$SID holds the space id and $DID the display id.
By default the space component invokes the script:
```bash
if [ "$SELECTED" = "true" ]; then
sketchybar -m set $NAME icon.highlight on
else
sketchybar -m set $NAME icon.highlight off
fi
```
which you can freely configure to your liking by supplying a different script to the space component.
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.
## Performance optimizations
*SketchyBar* can be configured to have a *very* small performance footprint. In the following I will highlight some optimizations that can be used to reduce the footprint further.
## 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 so please post the issues you encounter. The default menu bar can be set to autohide and this should still work.
Important: <br>
I 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 component 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 but can be modified with all the options available for simple items.
The command can be overloaded by providing a *window_owner* and a *window_name*
```bash
sketchybar -m add component alias <window_owner>,<window_name> <position>
```
this way the default system items can also be slurped into sketchybar, e.g.:
Owner: Control Center, Name: Bluetooth <br>
Owner: Control Center, Name: WiFi <br>
Owner: Control Center Name: Sound
Owner: Control Center, Name: UserSwitcher <br>
Owner: TextInputSwitcher, Name: Keyboard Input <br>
Owner: SystemUIServer, Name: AppleTimeMachineExtra <br>
Or the individual widgets of [Stats](https://github.com/exelban/stats):<br>
Owner: Stats Name: CPU_Mini<br>
Owner: Stats Name: RAM_Mini<br>
Owner: Stats Name: Network_Speed<br>
etc...<br>
All further default menu items currently available on your system can be found via the command:
```bash
sketchybar -m query default_menu_items
```
### Group Items in a Bracket for e.g. colored sections
This feature is only on HEAD currently.
It is possible to bracket together items via the command (see [this](https://github.com/FelixKratz/SketchyBar/discussions/12#discussioncomment-1455842) discussion for an example):
```bash
sketchybar -m add component bracket <name> <first item name> ... <n-th item name>
```
or with batching
```bash
sketchybar -m batch --add component bracket <name> <first item name> ... <n-th item name>
```
The first item must always be the one listed earliest in the config. It is now possible to
set properties for the bracket, just as for any item or component. Brackets currently only support all background features.
E.g., if I wanted a colored background around *all* my space components (which are named *code*, *writing*, *reading* and *entertainment*) I would set it up like this:
```bash
sketchybar -m batch --add component bracket primary_spaces code writing reading entertainment \
\
--set primary_spaces background.color=0xffffffff \
background.corner_radius=4 \
background.height=20
```
this draws a white background below all my space components. I plan to expand the capability of item brackets significantly in the future.
* Batch together configuration commands where ever possible.
* Set items to be *lazy*, e.g. I have an alias component in my bar that updates every *2* seconds, thus I set all *non-reactive* items to *lazy=on*,
and only the ones that should react to change instantaneously to *lazy=off*.
* Set *updates=when_shown* for items that do not need to run their script if they are not rendered.
* Reduce the *update_freq* of *scripts* and *aliases* and use event-driven scripting when ever possible.
* Do not add *aliases* to apps that are not always running, otherwise sketchybar searches for them continously.
## Credits
This project was forked from *[spacebar](https://github.com/cmacrae/spacebar)* and completely reimagined and rewritten. <br>

54
UPDATE.md Normal file
View file

@ -0,0 +1,54 @@
# v1.4.x -> v2.0.0
This document highlights the steps needed to update an existing sketchybar configuration to v2.0.0.
## Command Structure
* The *batch* command does not exist anymore, you can simply remove all occurences of *batch* in your configuration and all should still work.
* The *non-batch* version of all commands has been removed and superseded. Now *all* commands are prefixed with *--*
and contain *<key>=<value>* pairs. If you have used the batch syntax exclusively, you do not need to change anything, except removing all occurences of *batch*.
* The keyword *component* has been trimmed, simply delete all occurences of *component* in the configuration.
## Renamed Properties
* *icon_font* -> *icon.font*
* *icon_color* -> *icon.color*
* *icon_highlight_color* -> *icon.highlight_color*
* *icon_padding_left* -> *icon.padding_left*
* *icon_padding_right* -> *icon.padding_right*
* *icon_highlight* -> *icon.highlight*
* *label_font* -> *label.font*
* *label_color* -> *label.color*
* *label_highlight_color* -> *label.highlight_color*
* *label_padding_left* -> *label.padding_left*
* *label_padding_right* -> *label.padding_right*
* *label_highlight* -> *label.highlight*
* *draws_background* -> *background.drawing*
* *background_color* -> *background.color*
* *background_height* -> *background.height*
* *background_border_color* -> *background.border_color*
* *background_corner_radius* -> *background.corner_radius*
* *background_border_width* -> *background.border_width*
* *background_padding_left* -> *background.padding_left*
* *background_padding_right* -> *background.padding_right*
* *graph_color* -> *graph.color*
* *graph_fill_color* -> *graph.fill_color*
* *graph_line_width* -> *graph.line_width*
## Removed Modifiers
* *nospace* modifier has been removed in favour of the *width* property. Set *width=0* for equivalent behaviour
## Removed/Renamed Domains
* *config* -> *--bar*
* *set* -> *--set*
* *add* -> *--add*
* *query* -> *--query*
* *update* -> *--update*
* *trigger* -> *--trigger*
* *subscribe* -> *--subscribe*
* *default* -> *--default*
* *freeze*
* *remove*
## Replaced Properites
* *scripting*, replaced with *updates*
* *enabled*, replaced with *updates* and *drawing*

View file

@ -180,10 +180,13 @@ void bar_draw_bar_items(struct bar* bar) {
SLSReenableUpdate(g_connection);
}
uint32_t g_count = 0;
void bar_redraw(struct bar* bar) {
if (bar->hidden) return;
if (bar->sid == 0) return;
g_count++;
printf("Draw Call %d for bar on display: %d\n", g_count, bar->adid);
int bar_left_final_item_x = g_bar_manager.background.padding_left;
int bar_right_first_item_x = bar->frame.size.width - g_bar_manager.background.padding_right;
int bar_center_first_item_x = (bar->frame.size.width - bar_manager_get_center_length_for_bar(&g_bar_manager, bar)) / 2;

View file

@ -13,19 +13,31 @@ struct bar_item* bar_item_create() {
return bar_item;
}
void bar_item_clear_pointers(struct bar_item* bar_item) {
bar_item->name = NULL;
bar_item->script = NULL;
bar_item->click_script = NULL;
bar_item->bounding_rects = NULL;
bar_item->group = NULL;
text_clear_pointers(&bar_item->icon);
text_clear_pointers(&bar_item->label);
}
void bar_item_inherit_from_item(struct bar_item* bar_item, struct bar_item* ancestor) {
bar_item->lazy = ancestor->lazy;
bar_item->updates = ancestor->updates;
bar_item->updates_only_when_shown = ancestor->updates_only_when_shown;
bar_item->drawing = ancestor->drawing;
text_destroy(&bar_item->icon);
text_destroy(&bar_item->label);
bar_item->icon = ancestor->icon;
bar_item->label = ancestor->label;
text_clear_pointers(&bar_item->icon);
text_clear_pointers(&bar_item->label);
char* name = bar_item->name;
char* script = bar_item->name;
char* click_script = bar_item->name;
memcpy(bar_item, ancestor, sizeof(struct bar_item));
bar_item_clear_pointers(bar_item);
bar_item->name = name;
bar_item->script = script;
bar_item->click_script = click_script;
text_set_font(&bar_item->icon, string_copy(ancestor->icon.font_name), true);
text_set_font(&bar_item->label, string_copy(ancestor->label.font_name), true);
text_set_string(&bar_item->icon, string_copy(ancestor->icon.string), true);
@ -33,12 +45,6 @@ void bar_item_inherit_from_item(struct bar_item* bar_item, struct bar_item* ance
bar_item_set_script(bar_item, string_copy(ancestor->script));
bar_item_set_click_script(bar_item, string_copy(ancestor->click_script));
bar_item->update_frequency = ancestor->update_frequency;
bar_item->cache_scripts = ancestor->cache_scripts;
bar_item->background = ancestor->background;
bar_item->y_offset = ancestor->y_offset;
}
void bar_item_init(struct bar_item* bar_item, struct bar_item* default_item) {
@ -50,12 +56,9 @@ void bar_item_init(struct bar_item* bar_item, struct bar_item* default_item) {
bar_item->selected = false;
bar_item->mouse_over = false;
bar_item->counter = 0;
bar_item->name = "";
bar_item->type = BAR_ITEM;
bar_item->update_frequency = 0;
bar_item->cache_scripts = false;
bar_item->script = "";
bar_item->click_script = "";
bar_item->position = BAR_POSITION_RIGHT;
bar_item->associated_display = 0;
bar_item->associated_space = 0;
@ -69,9 +72,14 @@ void bar_item_init(struct bar_item* bar_item, struct bar_item* default_item) {
bar_item->bounding_rects = NULL;
bar_item->group = NULL;
bar_item->has_alias = false;
bar_item->has_graph = false;
bar_item->name = string_copy("");
bar_item->script = string_copy("");
bar_item->click_script = string_copy("");
text_init(&bar_item->icon);
text_init(&bar_item->label);
background_init(&bar_item->background);
@ -172,9 +180,9 @@ void bar_item_set_type(struct bar_item* bar_item, char type) {
if (type == BAR_COMPONENT_SPACE) {
bar_item_set_script(bar_item, string_copy("if [ \"$SELECTED\" = \"true\" ]; then "
"sketchybar -m set $NAME icon.highlight on;"
"sketchybar -m --set $NAME icon.highlight=on;"
"else "
"sketchybar -m set $NAME icon.highlight off;"
"sketchybar -m --set $NAME icon.highlight=off;"
" fi"));
bar_item->update_mask |= UPDATE_SPACE_CHANGE;

View file

@ -231,7 +231,7 @@ void bar_manager_update_space_components(struct bar_manager* bar_manager, bool f
}
void bar_manager_update(struct bar_manager* bar_manager, bool forced) {
if (bar_manager->frozen) return;
if (bar_manager->frozen && !forced) return;
bool needs_refresh = false;
for (int i = 0; i < bar_manager->bar_item_count; i++) {
needs_refresh |= bar_item_update(bar_manager->bar_items[i], NULL, forced);

View file

@ -55,22 +55,9 @@ static void handle_domain_push(FILE* rsp, struct token domain, char* message) {
struct bar_item* bar_item = g_bar_manager.bar_items[item_index_for_name];
graph_push_back(&bar_item->graph, token_to_float(y));
bar_item_needs_update(bar_item);
if (bar_item_is_shown(bar_item)) bar_manager_refresh(&g_bar_manager, false);
}
// Syntax: sketchybar -m remove <item>
static void handle_domain_remove(FILE* rsp, struct token domain, char* message) {
struct token command = get_token(&message);
if (token_equals(command, COMMAND_ADD_ITEM) || token_equals(command, COMMAND_ADD_COMPONENT)) {
struct token name = get_token(&message);
int index = bar_manager_get_item_index_for_name(&g_bar_manager, name.text);
if (index < 0) return;
bar_manager_destroy_item(&g_bar_manager, g_bar_manager.bar_items[index]);
}
bar_manager_refresh(&g_bar_manager, true);
}
// Syntax: sketchybar -m add <item|component|plugin> (<identifier>) <name> <position>
// Syntax: sketchybar -m add <item|component identifer> <name> <position>
static void handle_domain_add(FILE* rsp, struct token domain, char* message) {
struct token command = get_token(&message);
@ -91,11 +78,10 @@ static void handle_domain_add(FILE* rsp, struct token domain, char* message) {
position = get_token(&message);
bar_item->position = position.text[0];
bar_item_set_type(bar_item, BAR_ITEM);
} else if (token_equals(command, COMMAND_ADD_COMPONENT)) {
struct token identifier = get_token(&message);
} else if (command.length > 0) {
name = get_token(&message);
bar_item_set_type(bar_item, identifier.text[0]);
bar_item_set_type(bar_item, command.text[0]);
if (bar_item->type == BAR_COMPONENT_GRAPH) {
position = get_token(&message);
bar_item->position = position.text[0];
@ -139,7 +125,7 @@ static void handle_domain_add(FILE* rsp, struct token domain, char* message) {
}
bar_item_set_name(bar_item, token_to_string(name));
bar_manager_refresh(&g_bar_manager, true);
bar_item_needs_update(bar_item);
}
static void message_parse_set_message_for_bar_item(FILE* rsp, struct bar_item* bar_item, char* message) {
@ -233,26 +219,10 @@ static void handle_domain_default(FILE* rsp, struct token domain, char* message)
message_parse_set_message_for_bar_item(rsp, &g_bar_manager.default_item, message);
}
// Syntax: sketchybar -m set <name> <property> <value>
static void handle_domain_set(FILE* rsp, struct token domain, char* message) {
struct token name = get_token(&message);
int item_index_for_name = bar_manager_get_item_index_for_name(&g_bar_manager, name.text);
if (item_index_for_name < 0) {
fprintf(rsp, "Name: %s not found in bar items \n", name.text);
printf("Name: %s not found in bar items \n", name.text);
return;
}
struct bar_item* bar_item = g_bar_manager.bar_items[item_index_for_name];
message_parse_set_message_for_bar_item(rsp, bar_item, message);
if (bar_item_is_shown(bar_item)) bar_manager_refresh(&g_bar_manager, false);
}
static void handle_domain_bar(FILE *rsp, struct token domain, char *message) {
static bool handle_domain_bar(FILE *rsp, struct token domain, char *message) {
struct token command = get_token(&message);
bool needs_refresh = false;
if (token_equals(command, PROPERTY_MARGIN)) {
struct token token = get_token(&message);
g_bar_manager.margin = token_to_uint32t(token);
@ -306,10 +276,9 @@ static void handle_domain_bar(FILE *rsp, struct token domain, char *message) {
else
needs_refresh = background_parse_sub_domain(&g_bar_manager.background, rsp, command, message);
if (needs_refresh) {
bar_manager_resize(&g_bar_manager);
bar_manager_refresh(&g_bar_manager, true);
}
return needs_refresh;
}
static char* reformat_batch_key_value_pair(struct token token) {
@ -337,64 +306,6 @@ static char* get_batch_line(char** message) {
else *message = cursor + 1;
return rbr_msg;
}
// Syntax: sketchybar -m batch --<mode> <key>=<value> ... <key>=<value> \
// --<mode> <key>=<value> ... <key>=<value>
static void handle_domain_batch(FILE* rsp, struct token domain, char* message) {
bar_manager_freeze(&g_bar_manager);
struct token command = get_token(&message);
while (command.text && command.length > 0) {
if (token_equals(command, COMMAND_BATCH_SET)) {
struct token name = get_token(&message);
int item_index_for_name = bar_manager_get_item_index_for_name(&g_bar_manager, name.text);
if (item_index_for_name < 0) {
fprintf(rsp, "Name: %s not found in bar items \n", name.text);
printf("Name: %s not found in bar items \n", name.text);
break;
}
struct bar_item* bar_item = g_bar_manager.bar_items[item_index_for_name];
struct token token = get_token(&message);
while (token.text && token.length > 0) {
char* rbr_msg = reformat_batch_key_value_pair(token);
if (!rbr_msg) break;
message_parse_set_message_for_bar_item(rsp, bar_item, rbr_msg);
free(rbr_msg);
if (message && message[0] == '-') break;
token = get_token(&message);
}
} else if (token_equals(command, COMMAND_BATCH_DEFAULT)) {
struct token token = get_token(&message);
while (token.text && token.length > 0) {
char* rbr_msg = reformat_batch_key_value_pair(token);
if (!rbr_msg) break;
handle_domain_default(rsp, domain, rbr_msg);
free(rbr_msg);
if (message && message[0] == '-') break;
token = get_token(&message);
}
} else if (token_equals(command, COMMAND_BATCH_BAR)) {
struct token token = get_token(&message);
while (token.text && token.length > 0) {
char* rbr_msg = reformat_batch_key_value_pair(token);
if (!rbr_msg) break;
handle_domain_bar(rsp, domain, rbr_msg);
free(rbr_msg);
if (message && message[0] == '-') break;
token = get_token(&message);
}
} else if (token_equals(command, COMMAND_BATCH_ADD)) {
char* rbr_msg = get_batch_line(&message);
handle_domain_add(rsp, domain, rbr_msg);
free(rbr_msg);
} else if (token_equals(command, COMMAND_BATCH_SUBSCRIBE)) {
char* rbr_msg = get_batch_line(&message);
handle_domain_subscribe(rsp, domain, rbr_msg);
free(rbr_msg);
}
command = get_token(&message);
}
bar_manager_unfreeze(&g_bar_manager);
bar_manager_refresh(&g_bar_manager, false);
}
static void handle_domain_query(FILE* rsp, struct token domain, char* message) {
struct token token = get_token(&message);
@ -415,43 +326,89 @@ static void handle_domain_query(FILE* rsp, struct token domain, char* message) {
} else if (token_equals(token, COMMAND_QUERY_DEFAULTS)) {
bar_item_serialize(&g_bar_manager.default_item, rsp);
}
}
void handle_message(int sockfd, char* message) {
FILE* rsp = fdopen(sockfd, "w");
struct token domain = get_token(&message);
if (token_equals(domain, DOMAIN_SET)){
handle_domain_set(rsp, domain, message);
} else if (token_equals(domain, DOMAIN_BATCH)){
handle_domain_batch(rsp, domain, message);
} else if (token_equals(domain, DOMAIN_PUSH)) {
handle_domain_push(rsp, domain, message);
} else if (token_equals(domain, DOMAIN_BAR)) {
handle_domain_bar(rsp, domain, message);
} else if (token_equals(domain, DOMAIN_ADD)){
handle_domain_add(rsp, domain, message);
} else if (token_equals(domain, DOMAIN_REMOVE)){
handle_domain_remove(rsp, domain, message);
} else if (token_equals(domain, DOMAIN_UPDATE)) {
bar_manager_update_space_components(&g_bar_manager, true);
bar_manager_update(&g_bar_manager, true);
bar_manager_refresh(&g_bar_manager, true);
} else if (token_equals(domain, DOMAIN_SUBSCRIBE)) {
handle_domain_subscribe(rsp, domain, message);
} else if (token_equals(domain, DOMAIN_DEFAULT)) {
handle_domain_default(rsp, domain, message);
} else if (token_equals(domain, DOMAIN_TRIGGER)) {
handle_domain_trigger(rsp, domain, message);
} else if (token_equals(domain, DOMAIN_QUERY)) {
handle_domain_query(rsp, domain, message);
} else {
fprintf(rsp, "unknown domain '%.*s'\n", domain.length, domain.text);
printf("unknown domain '%.*s'\n", domain.length, domain.text);
bar_manager_freeze(&g_bar_manager);
struct token command = get_token(&message);
bool bar_needs_refresh = false;
while (command.text && command.length > 0) {
if (token_equals(command, DOMAIN_SET)) {
struct token name = get_token(&message);
int item_index_for_name = bar_manager_get_item_index_for_name(&g_bar_manager, name.text);
if (item_index_for_name < 0) {
fprintf(rsp, "Name: %s not found in bar items \n", name.text);
printf("Name: %s not found in bar items \n", name.text);
break;
}
struct bar_item* bar_item = g_bar_manager.bar_items[item_index_for_name];
struct token token = get_token(&message);
while (token.text && token.length > 0) {
char* rbr_msg = reformat_batch_key_value_pair(token);
if (!rbr_msg) break;
message_parse_set_message_for_bar_item(rsp, bar_item, rbr_msg);
free(rbr_msg);
if (message && message[0] == '-') break;
token = get_token(&message);
}
} else if (token_equals(command, DOMAIN_DEFAULT)) {
struct token token = get_token(&message);
while (token.text && token.length > 0) {
char* rbr_msg = reformat_batch_key_value_pair(token);
if (!rbr_msg) break;
handle_domain_default(rsp, command, rbr_msg);
free(rbr_msg);
if (message && message[0] == '-') break;
token = get_token(&message);
}
} else if (token_equals(command, DOMAIN_BAR)) {
struct token token = get_token(&message);
while (token.text && token.length > 0) {
char* rbr_msg = reformat_batch_key_value_pair(token);
if (!rbr_msg) break;
bar_needs_refresh |= handle_domain_bar(rsp, command, rbr_msg);
free(rbr_msg);
if (message && message[0] == '-') break;
token = get_token(&message);
}
} else if (token_equals(command, DOMAIN_ADD)) {
char* rbr_msg = get_batch_line(&message);
handle_domain_add(rsp, command, rbr_msg);
free(rbr_msg);
} else if (token_equals(command, DOMAIN_SUBSCRIBE)) {
char* rbr_msg = get_batch_line(&message);
handle_domain_subscribe(rsp, command, rbr_msg);
free(rbr_msg);
} else if (token_equals(command, DOMAIN_PUSH)) {
char* rbr_msg = get_batch_line(&message);
handle_domain_push(rsp, command, rbr_msg);
free(rbr_msg);
} else if (token_equals(command, DOMAIN_UPDATE)) {
bar_manager_update_space_components(&g_bar_manager, true);
bar_manager_update(&g_bar_manager, true);
bar_needs_refresh = true;
} else if (token_equals(command, DOMAIN_TRIGGER)) {
char* rbr_msg = get_batch_line(&message);
handle_domain_trigger(rsp, command, message);
free(rbr_msg);
} else if (token_equals(command, DOMAIN_QUERY)) {
handle_domain_query(rsp, command, message);
} else {
fprintf(rsp, "unknown domain '%.*s'\n", command.length, command.text);
printf("unknown domain '%.*s'\n", command.length, command.text);
}
command = get_token(&message);
}
bar_manager_unfreeze(&g_bar_manager);
if (bar_needs_refresh) {
bar_manager_resize(&g_bar_manager);
bar_manager_refresh(&g_bar_manager, true);
}
else {
bar_manager_refresh(&g_bar_manager, false);
}
if (rsp) fclose(rsp);
}

View file

@ -1,30 +1,21 @@
#ifndef MESSAGE_H
#define MESSAGE_H
#define DOMAIN_BATCH "batch"
#define COMMAND_BATCH_BAR "--bar"
#define COMMAND_BATCH_ADD "--add"
#define COMMAND_BATCH_SET "--set"
#define COMMAND_BATCH_DEFAULT "--default"
#define COMMAND_BATCH_SUBSCRIBE "--subscribe"
#define DOMAIN_ADD "add"
#define DOMAIN_ADD "--add"
#define COMMAND_ADD_ITEM "item"
#define COMMAND_ADD_COMPONENT "component"
#define COMMAND_ADD_EVENT "event"
#define DOMAIN_REMOVE "remove"
#define DOMAIN_UPDATE "--update"
#define DOMAIN_UPDATE "update"
#define DOMAIN_PUSH "--push"
#define DOMAIN_PUSH "push"
#define DOMAIN_TRIGGER "--trigger"
#define DOMAIN_TRIGGER "trigger"
#define DOMAIN_DEFAULT "default"
#define DOMAIN_DEFAULT "--default"
#define COMMAND_DEFAULT_RESET "reset"
#define DOMAIN_SET "set"
#define DOMAIN_SET "--set"
#define SUB_DOMAIN_ICON "icon"
#define SUB_DOMAIN_LABEL "label"
@ -60,7 +51,7 @@
#define PROPERTY_CACHE_SCRIPTS "cache_scripts"
#define PROPERTY_LAZY "lazy"
#define DOMAIN_BAR "bar"
#define DOMAIN_BAR "--bar"
#define PROPERTY_POSITION "position"
#define PROPERTY_MARGIN "margin"
#define PROPERTY_DISPLAY "display"
@ -68,7 +59,7 @@
#define PROPERTY_HIDDEN "hidden"
#define PROPERTY_FONT_SMOOTHING "font_smoothing"
#define DOMAIN_SUBSCRIBE "subscribe"
#define DOMAIN_SUBSCRIBE "--subscribe"
#define COMMAND_SUBSCRIBE_FRONT_APP_SWITCHED "front_app_switched"
#define COMMAND_SUBSCRIBE_SPACE_CHANGE "space_change"
#define COMMAND_SUBSCRIBE_DISPLAY_CHANGE "display_change"
@ -77,7 +68,7 @@
#define COMMAND_SUBSCRIBE_MOUSE_EXITED "mouse.exited"
#define COMMAND_SUBSCRIBE_MOUSE_CLICKED "mouse.clicked"
#define DOMAIN_QUERY "query"
#define DOMAIN_QUERY "--query"
#define COMMAND_QUERY_DEFAULT_ITEMS "default_menu_items"
#define COMMAND_QUERY_ITEM "item"
#define COMMAND_QUERY_DEFAULTS "defaults"

View file

@ -12,8 +12,8 @@
#define CONFIG_OPT_LONG "--config"
#define CONFIG_OPT_SHRT "-c"
#define MAJOR 1
#define MINOR 4
#define MAJOR 2
#define MINOR 0
#define PATCH 0
extern int SLSMainConnectionID(void);