Skip to content

5. Custom State Variables

rei2hu edited this page Nov 25, 2018 · 5 revisions

Custom State Variables

Due to the flexibility of swayblocks, namely that it doesn't care what you throw at it 99% of the time, you can hide your own variables in the program by using the custom set event. This is totally intended and not something I came across while playing around.


Simple Setup

The simplest way to set up custom variables is to modify the :default property of a script. For example

:default => %{
  "_timer" => 20,
  "_paused" => true
}

Now whenever the block is clicked, you'll notice that there are _timer and _paused keys in the block state when logging it.

#!/bin/python
import json, sys
block_status = json.loads(sys.argv[2]) # remember that the block status is passed as the second argument
sys.stderr.write(json.dumps(block_status) + "\n") # check log file after redirecting stderr to see output.

Using the set event

You can also use the set event to add and even modify variables. For example with the python script we add the _timer variable to the block if it doesn't exist.

#!/bin/python
import sys, json, os
click_info = json.loads(sys.argv[1])
block_statuses = json.loads(sys.argv[2])
block_status = block_statuses[int(click_info["instance"])]
with open(os.path.expanduser("~/.swayblocks.pipe"), "w") as fifo:
    if "_timer" not in block_status:
        block_status["_timer"] = 20
        fifo.write("{\"action\":\"set\", \"name\":\"~/.config/swayblocks/scripts/testblock\", \"key\":\"content\", \"value\":%s}" % json.dumps(json.dumps(block_status)))
        fifo.write("\n")

We need to use json.dumps twice to turn the dict into an escaped string.


Example

By using this idea, we can create a block that acts as a timer:

#!/bin/python
import sys, json, os, time

click_info = json.loads(sys.argv[1])
block_statuses = json.loads(sys.argv[2])
block_status = block_statuses[int(click_info["instance"])]

with open(os.path.expanduser("~/.swayblocks.pipe"), "w") as fifo:
    # we can append secret variables to the block states
    if "_timer" in block_status:
        duration = block_status["_timer"]
    else:
        duration = 10
        block_status["_timer"] = 10
        block_status["_paused"] = True

    if click_info["button"] == 1 and block_status["_paused"]: # left click to start the timer
        block_status["full_text"] = block_status["full_text"][:-1] # remove the p
        block_status["_paused"] = False
    if click_info["button"] == 3 and not block_status["_paused"]: # right click to pause the timer
        block_status["full_text"] += "p"
        block_status["_paused"] = True
    elif click_info["button"] == 4 and block_status["_paused"]: # scroll wheel to modify timer when paused
        duration += 1
        block_status["_timer"] = duration
        block_status["full_text"] = str(duration) + "p"
    elif click_info["button"] == 5 and block_status["_paused"]:
        duration -= 1
        block_status["_timer"] = duration
        block_status["full_text"] = str(duration) + "p"
    elif click_info["button"] == 100 and not block_status["_paused"]: # a custom button used to decrement the timer
        duration -= 1
        block_status["_timer"] = duration
        block_status["full_text"] = str(duration)

    fifo.write("{\"action\":\"set\", \"name\":\"~/.config/swayblocks/scripts/testblock\", \"key\":\"content\", \"value\":%s}" % json.dumps(json.dumps(block_status)))
    fifo.write("\n")
    fifo.write("{\"action\":\"refresh\", \"name\":\"\"}")
    fifo.write("\n")
    fifo.flush() # flush to prevent race conditions

    if duration > 0 and click_info["button"] == 100 and not block_status["_paused"]:
        time.sleep(1)
        fifo.write("{\"button\": 100, \"name\":\"~/.config/swayblocks/scripts/testblock\", \"instance\": 0}")
        fifo.write("\n")
    elif click_info["button"] == 1:
        fifo.write("{\"button\": 100, \"name\":\"~/.config/swayblocks/scripts/testblock\", \"instance\": 0}")
        fifo.write("\n")

Notice that we are also taking advantage of the ability to fake clicks to make the script call itself over and over again (I don't think button 100 will occur naturally):

fifo.write("{\"button\": 100, \"name\":\"~/.config/swayblocks/scripts/testblock\", \"instance\": 0}")
Clone this wiki locally