diff --git a/Program.cs b/Program.cs
index 807628a9737feee7fef5f22d08eebde4a9439432..457b63dd614c02b679462f142f7cda4d66e46d4f 100644
--- a/Program.cs
+++ b/Program.cs
@@ -47,6 +47,17 @@ static class POSIX
public static int SIGUSR1 = 10;
public static int EEXIST = 17;
public static int ERRNO { get => Marshal.GetLastPInvokeError();}
+ public static void Bash(string cmd)
+ {
+ var process = new Process();
+ process.StartInfo.FileName = "bash";
+ process.StartInfo.Arguments = "";
+ process.StartInfo.RedirectStandardInput = true;
+ process.Start();
+ TextWriter stdin = process.StandardInput;
+ stdin.Write(cmd);
+ stdin.Close();
+ }
}
static class ProcesExtended
@@ -97,6 +108,33 @@ enum Markup
Pango
}
+record Coordinates(
+ int X,
+ int Y
+ );
+
+enum MouseButton
+{
+ Left,
+ Right,
+ Middle
+}
+
+[Flags]
+enum Modifiers
+{
+ Shift=1,
+ Ctrl=2
+}
+
+record ClickEvent(
+ Coordinates Relative, // relative_x, relative_y
+ Coordinates Size, // width, height
+ MouseButton Button,
+ Coordinates? Absolute = null, // x, y
+ Coordinates? Output = null, // output_x, output_y
+ Modifiers Modifiers = 0
+ );
record Block(
string Text,
@@ -114,7 +152,8 @@ record Block(
bool Urgent = false,
bool Separator = true,
int? SeparatorBlockWidth=null,
- Markup Markup = Markup.None
+ Markup Markup = Markup.None,
+ Action<ClickEvent>? OnClick=null
);
@@ -417,14 +456,82 @@ class StatusBarTerminal: StatusBarPlainText
}
class StatusBarI3: RootStatusBar
{
- public StatusBarI3(FileInfo configFile):base(configFile){}
+ Thread? inputThread;
+ record HistoryElement(
+ long time_ms,
+ long id,
+ IEnumerable<Block> data
+ );
+ Queue<HistoryElement> history = new(); // for finding correct lambda in inputThread
+ int outputCounter = 0;
+ public StatusBarI3(FileInfo configFile, bool doInput):base(configFile)
+ {
+ Console.Error.Flush();
+ if(doInput)
+ {
+ inputThread = new Thread(this.inputThreadFunc);
+ inputThread.IsBackground = true;
+ inputThread.Start();
+ }
+ }
+ void inputThreadFunc()
+ {
+ Console.ReadLine(); // read "["
+ while(true)
+ {
+ #pragma warning disable 8602
+ string? line = Console.ReadLine();
+ if(line == null) throw new Exception("I3bar close input");
+ if(line[0] == ',') line = line[1..];
+
+ JsonObject json = JsonObject.Parse(line).AsObject();
+ MouseButton button;
+ int jsonButton = json["button"].AsValue().GetValue<int>();
+ if(jsonButton == 1) button = MouseButton.Left; else
+ if(jsonButton == 2) button = MouseButton.Middle; else
+ if(jsonButton == 3) button = MouseButton.Left; else
+ break;
+ var ev = new ClickEvent(
+ Relative: new Coordinates(json["relative_x"].AsValue().GetValue<int>(), json["relative_y"].AsValue().GetValue<int>()),
+ Size: new Coordinates(json["height"].AsValue().GetValue<int>(), json["width"].AsValue().GetValue<int>()),
+ Button: button
+ );
+ string name = json["name"].AsValue().GetValue<string>();
+ int outputId = int.Parse(name.Split(".")[0]);
+ int blockId = int.Parse(name.Split(".")[1]);
+ HistoryElement currentBar;
+ lock(history)
+ {
+ while(history.Count > 0 && history.Peek().id < outputId)
+ history.Dequeue();
+ if(history.Count <= 0) break;
+ currentBar = history.Peek();
+ }
+ var block = currentBar.data.ElementAt(blockId);
+ if(block.OnClick != null)
+ block.OnClick(ev);
+ #pragma warning restore 8602
+ }
+ }
override protected void initOutput(TextWriter w)
{
- w.WriteLine("{\"version\":1}");
+ if(inputThread == null)
+ w.WriteLine("{\"version\":1}");
+ else
+ w.WriteLine("{\"version\":1, \"click_events\": true }");
w.WriteLine("[{}");
}
override protected void format(TextWriter w, List<Block> elements)
{
+ if(inputThread != null)
+ {
+ lock(history)
+ {
+ while(history.Count > 0 && history.Peek().time_ms < Environment.TickCount64 - 1000)
+ history.Dequeue();
+ history.Enqueue(new HistoryElement(Environment.TickCount64, outputCounter, elements));
+ }
+ }
JsonNode? intStringUnion(int? _int, string? _string)
{
JsonNode? n = null;
@@ -432,7 +539,9 @@ class StatusBarI3: RootStatusBar
if(_string != null) n = _string;
return n;
}
+ int i = 0;
var json = new JsonArray((from e in elements select new JsonObject(){
+ ["name"] = $"{outputCounter}.{i++}",
["full_text"] = e.Text,
["short_text"] = e.ShortText,
["color"] = e.Color?.ToHex(),
@@ -453,6 +562,7 @@ class StatusBarI3: RootStatusBar
opt.DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull;
w.Write(",");
w.WriteLine(json.ToJsonString(opt));
+ outputCounter++;
}
}
@@ -504,10 +614,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.");
var c_i3 = new Command("i3", "Comunicate with i3bar.");
rootCommand.Add(c_i3);
- c_i3.SetHandler(async (config) =>
+ var c_i3_input = new Option<bool>
+ ("--input", "Read mouse clicks.");
+ c_i3_input.AddAlias("-i");
+ c_i3.Add(c_i3_input);
+ c_i3.SetHandler(async (config, input) =>
{
- (new StatusBarI3(config)).Run(Console.Out);
- }, configOption);
+ (new StatusBarI3(config, input)).Run(Console.Out);
+ }, configOption, c_i3_input);
rootCommand.Invoke(args);
return 0;