Skip to content

Commit

Permalink
Add ControllsWidget (#203)
Browse files Browse the repository at this point in the history
  • Loading branch information
JannisPetschenka authored Feb 9, 2023
1 parent 6878505 commit 5779017
Show file tree
Hide file tree
Showing 9 changed files with 507 additions and 1 deletion.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ These widgets can be customized, added, removed and even reordered
- Notifications (Will always be visible)
- Label
- Mpris (Media player controls for Spotify, Firefox, Chrome, etc...)
- Menubar with dropdown and buttons
- Button grid

## Planned Features

Expand Down
119 changes: 119 additions & 0 deletions man/swaync.5.scd
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ config file to be able to detect config errors
optional: true ++
*mpris*++
optional: true ++
*menubar*++
optional: true ++
*buttons-grid*++
optional: true ++
description: ++
Which order and which widgets to display. ++
If the \"notifications\" widget isn't specified, it ++
Expand Down Expand Up @@ -280,6 +284,89 @@ config file to be able to detect config errors
default: 12 ++
description: The border radius of the album art. ++
description: A widget that displays multiple music players. ++
*menubar*++
type: object ++
css classes: ++
widget-menubar ++
.widget-menubar>box>.menu-button-bar ++
name of element given after menu or buttons with # ++
patternProperties: ++
menu#<name>: ++
type: object ++
properties: ++
label: ++
type: string ++
optional: true ++
default: "Menu" ++
description: Label of button to show/hide menu dropdown ++
position: ++
type: string ++
optional: true ++
default: "right" ++
description: Horizontal position of the button in the bar ++
enum: ["right", "left"] ++
actions: ++
type: array ++
Default values: [] ++
Valid array values: ++
type: object ++
properties: ++
label: ++
type: string ++
default: "label" ++
description: Text to be displayed in button ++
command: ++
type: string ++
default: "" ++
description: "Command to be executed on click" ++
description: A list of actions containing a label and a command ++
description: A button to reveal a dropdown with action-buttons ++
buttons#<name>: ++
type: object ++
properties: ++
position: ++
type: string ++
optional: true ++
default: "right" ++
description: Horizontal position of the buttons in the bar ++
enum: ["right", "left"] ++
actions: ++
type: array ++
Default values: [] ++
Valid array values: ++
type: object ++
properties: ++
label: ++
type: string ++
default: "label" ++
description: Text to be displayed in button ++
command: ++
type: string ++
default: "" ++
description: "Command to be executed on click" ++
description: A list of actions containing a label and a command ++
description: A list of buttons to be displayed in the menu-button-bar ++
*buttons-grid*++
type: object ++
css class: widget-buttons (access buttons with >flowbox>flowboxchild>button) ++
properties: ++
actions: ++
type: array ++
Default values: [] ++
Valid array values: ++
type: object ++
properties: ++
label: ++
type: string ++
default: "label" ++
description: Text to be displayed in button ++
command: ++
type: string ++
default: "" ++
description: "Command to be executed on click" ++
description: A list of actions containing a label and a command ++
description: A grid of buttons that execute shell commands ++

example:
```
{
Expand All @@ -299,6 +386,38 @@ config file to be able to detect config errors
"mpris": {
"image-size": 96,
"image-radius": 12
},
"menubar": {
"menu#power": {
"label": "Power",
"position": "right",
"actions": [
{
"label": "Shut down",
"command": "systemctl poweroff"
},
...
]
},
"buttons#screenshot": {
"position": "left",
"actions": [
{
"label": "Screenshot",
"command": "grim"
},
...
]
}
},
"buttons": {
"actions": [
{
"label": "wifi",
"command": "rofi-wifi-menu"
},
...
]
}
}
}
Expand Down
76 changes: 76 additions & 0 deletions src/configSchema.json
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,12 @@
},
"^mpris(#[a-zA-Z0-9_-]{1,}){0,1}?$": {
"$ref": "#/widgets/mpris"
},
"^buttons-grid(#[a-zA-Z0-9_-]{1,}){0,1}?$": {
"$ref": "#/widgets/buttons"
},
"^menubar(#[a-zA-Z0-9_-]{1,}){0,1}?$": {
"$ref": "#/widgets/menubar"
}
}
}
Expand Down Expand Up @@ -339,6 +345,76 @@
"default": 12
}
}
},
"buttons-grid": {
"type": "object",
"description": "A widget to add a grid of buttons that execute shell commands",
"additionalProperties": false,
"properties": {
"actions": {
"type": "array",
"description": "A list of actions containing a label and a command",
"items": {
"type": "object",
"properties": {
"label": {
"type": "string",
"description": "Text to be displayed in button",
"default": "label"
},
"command": {
"type": "string",
"description": "Command to be executed on click",
"default": ""
}
}
}
}
}
},
"menubar": {
"type": "object",
"description": "A bar that contains action-buttons and buttons to open a dropdown with action-buttons",
"additionalProperties": false,
"patternProperties": {
"^menu(#[a-zA-Z0-9_-]{1,}){0,1}?$": {
"type": "object",
"description": "A button that opens a dropdown with action-buttons",
"additionalProperties": false,
"properties": {
"label": {
"type": "string",
"description": "Text to be displayed in button",
"default": "Menu"
},
"position": {
"type": "string",
"description": "Horizontal position of the button in the bar",
"default": "right",
"enum": ["right", "left"]
},
"actions": {
"$ref" : "#/widgets/buttons-grid/properties/actions"
}
}
},
"^buttons(#[a-zA-Z0-9_-]{1,}){0,1}?$": {
"type": "object",
"description": "A list of action-buttons to be displayed in the topbar",
"additionalProperties": false,
"properties": {
"position": {
"type": "string",
"description": "Horizontal position of the button in the bar",
"default": "right",
"enum": ["right", "left"]
},
"actions": {
"$ref" : "#/widgets/buttons-grid/properties/actions"
}
}
}
}
}
}
}
42 changes: 41 additions & 1 deletion src/controlCenter/widgets/baseWidget.vala
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Posix;

namespace SwayNotificationCenter.Widgets {
public abstract class BaseWidget : Gtk.Box {
public abstract string widget_name { get; }
Expand Down Expand Up @@ -39,7 +41,7 @@ namespace SwayNotificationCenter.Widgets {

public virtual void on_cc_visibility_change (bool value) {}

protected T? get_prop<T> (Json.Object config, string value_key) {
protected T ? get_prop<T> (Json.Object config, string value_key) {
if (!config.has_member (value_key)) {
debug ("%s: Config doesn't have key: %s!\n", key, value_key);
return null;
Expand Down Expand Up @@ -70,5 +72,43 @@ namespace SwayNotificationCenter.Widgets {
return null;
}
}

protected Json.Array ? get_prop_array (Json.Object config, string value_key) {
if (!config.has_member (value_key)) {
debug ("%s: Config doesn't have key: %s!\n", key, value_key);
return null;
}
var member = config.get_member (value_key);
if (member.get_node_type () != Json.NodeType.ARRAY) {
debug ("Unable to find Json Array for member %s", value_key);
}
return config.get_array_member (value_key);
}

protected Action[] parse_actions (Json.Array actions) {
Action[] res = new Action[actions.get_length ()];
for (int i = 0; i < actions.get_length (); i++) {
string label = actions.get_object_element (i).get_string_member_with_default ("label", "label");
string command = actions.get_object_element (i).get_string_member_with_default ("command", "");
res[i] = Action () {
label = label,
command = command
};
}
return res;
}

protected void execute_command (string cmd) {
pid_t pid;
int status;
if ((pid = fork ()) < 0) {
perror ("fork()");
}
if (pid == 0) { // Child process
execl ("/bin/sh", "sh", "-c", cmd);
exit (EXIT_FAILURE); // should not return from execl
}
waitpid (pid, out status, 1);
}
}
}
39 changes: 39 additions & 0 deletions src/controlCenter/widgets/buttonsGrid/buttonsGrid.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using GLib;

namespace SwayNotificationCenter.Widgets {

public class ButtonsGrid : BaseWidget {
public override string widget_name {
get {
return "buttons-grid";
}
}

Action[] actions;

public ButtonsGrid (string suffix, SwayncDaemon swaync_daemon, NotiDaemon noti_daemon) {
base (suffix, swaync_daemon, noti_daemon);

Json.Object ? config = get_config (this);
if (config != null) {
Json.Array a = get_prop_array (config, "actions");
if (a != null) actions = parse_actions (a);
}

Gtk.FlowBox container = new Gtk.FlowBox ();
container.set_selection_mode (Gtk.SelectionMode.NONE);
pack_start (container, true, true, 0);

// add action to container
foreach (var act in actions) {
Gtk.Button b = new Gtk.Button.with_label (act.label);

b.clicked.connect (() => execute_command (act.command));

container.insert (b, -1);
}

show_all ();
}
}
}
6 changes: 6 additions & 0 deletions src/controlCenter/widgets/factory.vala
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ namespace SwayNotificationCenter.Widgets {
case "mpris":
widget = new Mpris.Mpris (suffix, swaync_daemon, noti_daemon);
break;
case "menubar":
widget = new Menubar (suffix, swaync_daemon, noti_daemon);
break;
case "buttons-grid":
widget = new ButtonsGrid (suffix, swaync_daemon, noti_daemon);
break;
default:
warning ("Could not find widget: \"%s\"!", key);
return null;
Expand Down
Loading

0 comments on commit 5779017

Please sign in to comment.