diff --git a/README.md b/README.md index 2f4d71f..cdcc51a 100644 --- a/README.md +++ b/README.md @@ -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 -``` -or when you want to batch configurations: -```bash -sketchybar -m batch --bar = ... = +sketchybar -m --bar = ... = ``` 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:
+
+ +### Adding items to sketchybar ```bash -sketchybar -m add item [optional: ] -``` -or with command batching: -```bash -sketchybar -m batch --add item [optional: ] +sketchybar -m --add item ``` 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 [optional: ] -``` -or for batching of commands: -```bash -sketchybar -m batch --add component [optional: ] -``` -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 -``` -here batching is also possible with: -```bash -sketchybar -m batch --set = ... = +sketchybar -m --set = ... = ``` where the *name* is used to target the item with this name. -An item always has the following structure in the bar:
-
-background_padding_left|-icon_padding_left-|-icon-|-icon_padding_right-|-label_padding_left-|-label-|-label_padding_right-|background_padding_right
+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 +sketchybar -m --default = ... = ``` -batching is again possible via: -```bash -sketchybar -m batch --default = ... = -``` -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 +``` + +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 +``` + +### Space -- Associate mission control spaces with an item +```bash +sketchybar -m --add space +``` +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 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 ... +``` +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:
+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 +``` +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 , +``` +this way the default system items can also be slurped into sketchybar, e.g.: +Owner: "Control Center", Name: Bluetooth
+Owner: "Control Center", Name: WiFi
+ +Or the individual widgets of [Stats](https://github.com/exelban/stats):
+Owner: Stats Name: CPU_Mini
+etc...
+ +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 ... -``` -the batching command is very similar: -```bash -sketchybar -m batch --subscribe ... +sketchybar -m --subscribe ... ``` 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:
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 [optional: ] -``` -and the batch version of this: -```bash -sketchybar -m batch --add event [optional: ] +sketchybar -m --add event [optional: ] ``` 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 +sketchybar -m --trigger ``` 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 -``` -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 -``` -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 +sketchybar -m --query item ``` 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:
-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 -``` -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 , -``` -this way the default system items can also be slurped into sketchybar, e.g.: - -Owner: Control Center, Name: Bluetooth
-Owner: Control Center, Name: WiFi
-Owner: Control Center Name: Sound -Owner: Control Center, Name: UserSwitcher
-Owner: TextInputSwitcher, Name: Keyboard Input
-Owner: SystemUIServer, Name: AppleTimeMachineExtra
- -Or the individual widgets of [Stats](https://github.com/exelban/stats):
-Owner: Stats Name: CPU_Mini
-Owner: Stats Name: RAM_Mini
-Owner: Stats Name: Network_Speed
-etc...
- -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 ... -``` -or with batching -```bash -sketchybar -m batch --add component bracket ... -``` -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.
diff --git a/UPDATE.md b/UPDATE.md new file mode 100644 index 0000000..88e965d --- /dev/null +++ b/UPDATE.md @@ -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 *=* 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* + diff --git a/src/bar.c b/src/bar.c index 6a50ea5..204e20a 100644 --- a/src/bar.c +++ b/src/bar.c @@ -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; diff --git a/src/bar_item.c b/src/bar_item.c index 73a2a31..5a94538 100644 --- a/src/bar_item.c +++ b/src/bar_item.c @@ -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; diff --git a/src/bar_manager.c b/src/bar_manager.c index 7a0e131..474f07b 100644 --- a/src/bar_manager.c +++ b/src/bar_manager.c @@ -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); diff --git a/src/message.c b/src/message.c index 219b0dc..915527a 100644 --- a/src/message.c +++ b/src/message.c @@ -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 -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 () +// Syntax: sketchybar -m add 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 -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 -- = ... = \ -// -- = ... = -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); } diff --git a/src/message.h b/src/message.h index 0a7c4bc..bb55f4a 100644 --- a/src/message.h +++ b/src/message.h @@ -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" diff --git a/src/sketchybar.c b/src/sketchybar.c index 180d52e..00f496f 100644 --- a/src/sketchybar.c +++ b/src/sketchybar.c @@ -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);