mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2024-12-26 21:58:10 +01:00
Write rest of new Lua API
This commit is contained in:
parent
97f9cf82d6
commit
f10bd933ca
10 changed files with 468 additions and 48 deletions
|
@ -10,6 +10,10 @@ local pinnacle = {
|
||||||
---@class Pinnacle
|
---@class Pinnacle
|
||||||
---@field private config_client Client
|
---@field private config_client Client
|
||||||
---@field input Input
|
---@field input Input
|
||||||
|
---@field output Output
|
||||||
|
---@field process Process
|
||||||
|
---@field tag Tag
|
||||||
|
---@field window Window
|
||||||
local Pinnacle = {}
|
local Pinnacle = {}
|
||||||
|
|
||||||
function Pinnacle:quit()
|
function Pinnacle:quit()
|
||||||
|
@ -34,6 +38,10 @@ function pinnacle.setup(config_fn)
|
||||||
local self = {
|
local self = {
|
||||||
config_client = config_client,
|
config_client = config_client,
|
||||||
input = require("pinnacle.input").new(config_client),
|
input = require("pinnacle.input").new(config_client),
|
||||||
|
process = require("pinnacle.process").new(config_client),
|
||||||
|
window = require("pinnacle.window").new(config_client),
|
||||||
|
output = require("pinnacle.output").new(config_client),
|
||||||
|
tag = require("pinnacle.tag").new(config_client),
|
||||||
}
|
}
|
||||||
setmetatable(self, { __index = Pinnacle })
|
setmetatable(self, { __index = Pinnacle })
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ local Client = {}
|
||||||
---@class GrpcRequestParams
|
---@class GrpcRequestParams
|
||||||
---@field service string
|
---@field service string
|
||||||
---@field method string
|
---@field method string
|
||||||
---@field request_type string?
|
---@field request_type string
|
||||||
---@field response_type string?
|
---@field response_type string?
|
||||||
---@field data table
|
---@field data table
|
||||||
|
|
||||||
|
@ -45,44 +45,6 @@ local Client = {}
|
||||||
function Client:unary_request(grpc_request_params)
|
function Client:unary_request(grpc_request_params)
|
||||||
local stream = self.conn:new_stream()
|
local stream = self.conn:new_stream()
|
||||||
|
|
||||||
local service = grpc_request_params.service
|
|
||||||
local method = grpc_request_params.method
|
|
||||||
local request_type = grpc_request_params.request_type or method .. "Request"
|
|
||||||
local response_type = grpc_request_params.response_type or "google.protobuf.Empty"
|
|
||||||
local data = grpc_request_params.data
|
|
||||||
|
|
||||||
local encoded_protobuf = assert(pb.encode(request_type, data), "wrong table schema")
|
|
||||||
|
|
||||||
local packed_prefix = string.pack("I1", 0)
|
|
||||||
local payload_len = string.pack(">I4", encoded_protobuf:len())
|
|
||||||
|
|
||||||
local body = packed_prefix .. payload_len .. encoded_protobuf
|
|
||||||
|
|
||||||
stream:write_headers(create_request_headers(service, method), false)
|
|
||||||
stream:write_chunk(body, true)
|
|
||||||
|
|
||||||
local response_headers = stream:get_headers()
|
|
||||||
-- TODO: check headers for errors
|
|
||||||
|
|
||||||
local response_body = stream:get_next_chunk()
|
|
||||||
local response = pb.decode(response_type, response_body)
|
|
||||||
|
|
||||||
print(inspect(response))
|
|
||||||
|
|
||||||
return response
|
|
||||||
end
|
|
||||||
|
|
||||||
---Send a async server streaming request to the compositor.
|
|
||||||
---
|
|
||||||
---`callback` will be called with every streamed response.
|
|
||||||
---
|
|
||||||
---If `response_type` is not specified then it will default to
|
|
||||||
---`google.protobuf.Empty`.
|
|
||||||
---@param grpc_request_params GrpcRequestParams
|
|
||||||
---@param callback fun(response: table)
|
|
||||||
function Client:server_streaming_request(grpc_request_params, callback)
|
|
||||||
local stream = self.conn:new_stream()
|
|
||||||
|
|
||||||
local service = grpc_request_params.service
|
local service = grpc_request_params.service
|
||||||
local method = grpc_request_params.method
|
local method = grpc_request_params.method
|
||||||
local request_type = grpc_request_params.request_type
|
local request_type = grpc_request_params.request_type
|
||||||
|
@ -102,9 +64,61 @@ function Client:server_streaming_request(grpc_request_params, callback)
|
||||||
local response_headers = stream:get_headers()
|
local response_headers = stream:get_headers()
|
||||||
-- TODO: check headers for errors
|
-- TODO: check headers for errors
|
||||||
|
|
||||||
|
local response_body = stream:get_next_chunk()
|
||||||
|
-- Skip the 1-byte compressed flag and the 4-byte message length
|
||||||
|
local response_body = response_body:sub(6)
|
||||||
|
local response = pb.decode(response_type, response_body)
|
||||||
|
|
||||||
|
print(inspect(response))
|
||||||
|
|
||||||
|
return response
|
||||||
|
end
|
||||||
|
|
||||||
|
---Send a async server streaming request to the compositor.
|
||||||
|
---
|
||||||
|
---`callback` will be called with every streamed response.
|
||||||
|
---
|
||||||
|
---If `response_type` is not specified then it will default to
|
||||||
|
---`google.protobuf.Empty`.
|
||||||
|
---@param grpc_request_params GrpcRequestParams
|
||||||
|
---@param callback fun(response: table)
|
||||||
|
function Client:server_streaming_request(grpc_request_params, callback)
|
||||||
|
-- print(inspect(grpc_request_params))
|
||||||
|
local stream = self.conn:new_stream()
|
||||||
|
|
||||||
|
local service = grpc_request_params.service
|
||||||
|
local method = grpc_request_params.method
|
||||||
|
local request_type = grpc_request_params.request_type
|
||||||
|
local response_type = grpc_request_params.response_type or "google.protobuf.Empty"
|
||||||
|
local data = grpc_request_params.data
|
||||||
|
|
||||||
|
local encoded_protobuf = assert(pb.encode(request_type, data), "wrong table schema")
|
||||||
|
|
||||||
|
local packed_prefix = string.pack("I1", 0)
|
||||||
|
local payload_len = string.pack(">I4", encoded_protobuf:len())
|
||||||
|
|
||||||
|
local body = packed_prefix .. payload_len .. encoded_protobuf
|
||||||
|
|
||||||
|
stream:write_headers(create_request_headers(service, method), false)
|
||||||
|
stream:write_chunk(body, true)
|
||||||
|
|
||||||
|
local response_headers = stream:get_headers()
|
||||||
|
-- local chunk = stream:get_next_chunk()
|
||||||
|
-- print(chunk, chunk:len())
|
||||||
|
-- TODO: check headers for errors
|
||||||
|
|
||||||
self.loop:wrap(function()
|
self.loop:wrap(function()
|
||||||
for response_body in stream:each_chunk() do
|
for response_body in stream:each_chunk() do
|
||||||
local response = pb.decode(response_type, response_body)
|
-- Skip the 1-byte compressed flag and the 4-byte message length
|
||||||
|
local response_body = response_body:sub(6)
|
||||||
|
|
||||||
|
local success, obj = pcall(pb.decode, response_type, response_body)
|
||||||
|
if not success then
|
||||||
|
print(obj)
|
||||||
|
os.exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local response = obj
|
||||||
callback(response)
|
callback(response)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -28,7 +28,7 @@ local function build_grpc_request_params(method, data)
|
||||||
return {
|
return {
|
||||||
service = service,
|
service = service,
|
||||||
method = method,
|
method = method,
|
||||||
request_type = req_type and prefix .. req_type,
|
request_type = req_type and prefix .. req_type or prefix .. method .. "Request",
|
||||||
response_type = resp_type and prefix .. resp_type,
|
response_type = resp_type and prefix .. resp_type,
|
||||||
data = data,
|
data = data,
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ local function build_grpc_request_params(method, data)
|
||||||
return {
|
return {
|
||||||
service = service,
|
service = service,
|
||||||
method = method,
|
method = method,
|
||||||
request_type = req_type and prefix .. req_type,
|
request_type = req_type and prefix .. req_type or prefix .. method .. "Request",
|
||||||
response_type = resp_type and prefix .. resp_type,
|
response_type = resp_type and prefix .. resp_type,
|
||||||
data = data,
|
data = data,
|
||||||
}
|
}
|
||||||
|
|
75
api/lua_grpc/pinnacle/process.lua
Normal file
75
api/lua_grpc/pinnacle/process.lua
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
---The protobuf absolute path prefix
|
||||||
|
local prefix = "pinnacle.process." .. require("pinnacle").version .. "."
|
||||||
|
local service = prefix .. "ProcessService"
|
||||||
|
|
||||||
|
---@type table<string, { request_type: string?, response_type: string? }>
|
||||||
|
---@enum (key) ProcessServiceMethod
|
||||||
|
local rpc_types = {
|
||||||
|
Spawn = {
|
||||||
|
response_type = "SpawnResponse",
|
||||||
|
},
|
||||||
|
SetEnv = {},
|
||||||
|
}
|
||||||
|
|
||||||
|
---Build GrpcRequestParams
|
||||||
|
---@param method ProcessServiceMethod
|
||||||
|
---@param data table
|
||||||
|
---@return GrpcRequestParams
|
||||||
|
local function build_grpc_request_params(method, data)
|
||||||
|
local req_type = rpc_types[method].request_type
|
||||||
|
local resp_type = rpc_types[method].response_type
|
||||||
|
|
||||||
|
---@type GrpcRequestParams
|
||||||
|
return {
|
||||||
|
service = service,
|
||||||
|
method = method,
|
||||||
|
request_type = req_type and prefix .. req_type or prefix .. method .. "Request",
|
||||||
|
response_type = resp_type and prefix .. resp_type,
|
||||||
|
data = data,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
---@class ProcessModule
|
||||||
|
local process = {}
|
||||||
|
|
||||||
|
---@class Process
|
||||||
|
---@field private config_client Client
|
||||||
|
local Process = {}
|
||||||
|
|
||||||
|
---@param args string[]
|
||||||
|
---@param callbacks { stdout: fun(line: string)?, stderr: fun(line: string)?, exit: fun(code: integer, msg: string)? }?
|
||||||
|
function Process:spawn(args, callbacks)
|
||||||
|
local callback = function() end
|
||||||
|
|
||||||
|
if callbacks then
|
||||||
|
callback = function(response)
|
||||||
|
if callbacks.stdout and response.stdout then
|
||||||
|
callbacks.stdout(response.stdout)
|
||||||
|
end
|
||||||
|
if callbacks.stderr and response.stderr then
|
||||||
|
callbacks.stderr(response.stderr)
|
||||||
|
end
|
||||||
|
if callbacks.exit and (response.exit_code or response.exit_message) then
|
||||||
|
callbacks.exit(response.exit_code, response.exit_message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.config_client:server_streaming_request(
|
||||||
|
build_grpc_request_params("Spawn", {
|
||||||
|
args = args,
|
||||||
|
once = false,
|
||||||
|
has_callback = callbacks ~= nil,
|
||||||
|
}),
|
||||||
|
callback
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
function process.new(config_client)
|
||||||
|
---@type Process
|
||||||
|
local self = { config_client = config_client }
|
||||||
|
setmetatable(self, { __index = Process })
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
return process
|
|
@ -32,7 +32,7 @@ local function build_grpc_request_params(method, data)
|
||||||
return {
|
return {
|
||||||
service = service,
|
service = service,
|
||||||
method = method,
|
method = method,
|
||||||
request_type = req_type and prefix .. req_type,
|
request_type = req_type and prefix .. req_type or prefix .. method .. "Request",
|
||||||
response_type = resp_type and prefix .. resp_type,
|
response_type = resp_type and prefix .. resp_type,
|
||||||
data = data,
|
data = data,
|
||||||
}
|
}
|
||||||
|
|
268
api/lua_grpc/pinnacle/window.lua
Normal file
268
api/lua_grpc/pinnacle/window.lua
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
---The protobuf absolute path prefix
|
||||||
|
local prefix = "pinnacle.prefix." .. require("pinnacle").version .. "."
|
||||||
|
local service = prefix .. "WindowService"
|
||||||
|
|
||||||
|
---@type table<string, { request_type: string?, response_type: string? }>
|
||||||
|
---@enum (key) WindowServiceMethod
|
||||||
|
local rpc_types = {
|
||||||
|
Close = {},
|
||||||
|
SetGeometry = {},
|
||||||
|
SetFullscreen = {},
|
||||||
|
SetMaximized = {},
|
||||||
|
SetFloating = {},
|
||||||
|
MoveToTag = {},
|
||||||
|
SetTag = {},
|
||||||
|
MoveGrab = {},
|
||||||
|
ResizeGrab = {},
|
||||||
|
Get = {
|
||||||
|
response_type = "GetResponse",
|
||||||
|
},
|
||||||
|
GetProperties = {
|
||||||
|
response_type = "GetPropertiesResponse",
|
||||||
|
},
|
||||||
|
AddWindowRule = {},
|
||||||
|
}
|
||||||
|
|
||||||
|
---Build GrpcRequestParams
|
||||||
|
---@param method WindowServiceMethod
|
||||||
|
---@param data table
|
||||||
|
---@return GrpcRequestParams
|
||||||
|
local function build_grpc_request_params(method, data)
|
||||||
|
local req_type = rpc_types[method].request_type
|
||||||
|
local resp_type = rpc_types[method].response_type
|
||||||
|
|
||||||
|
---@type GrpcRequestParams
|
||||||
|
return {
|
||||||
|
service = service,
|
||||||
|
method = method,
|
||||||
|
request_type = req_type and prefix .. req_type or prefix .. method .. "Request",
|
||||||
|
response_type = resp_type and prefix .. resp_type,
|
||||||
|
data = data,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
---@class WindowHandleModule
|
||||||
|
local window_handle = {}
|
||||||
|
|
||||||
|
---@class WindowHandle
|
||||||
|
---@field private config_client Client
|
||||||
|
---@field id integer
|
||||||
|
local WindowHandle = {}
|
||||||
|
|
||||||
|
---@class WindowModule
|
||||||
|
---@field private handle WindowHandleModule
|
||||||
|
local window = {}
|
||||||
|
window.handle = window_handle
|
||||||
|
|
||||||
|
---@class Window
|
||||||
|
---@field private config_client Client
|
||||||
|
local Window = {}
|
||||||
|
|
||||||
|
---Get all windows.
|
||||||
|
---
|
||||||
|
---@return WindowHandle[]
|
||||||
|
function Window:get_all()
|
||||||
|
local response = self.config_client:unary_request(build_grpc_request_params("Get", {}))
|
||||||
|
|
||||||
|
local handles = window_handle.new_from_table(self.config_client, response.window_ids)
|
||||||
|
|
||||||
|
return handles
|
||||||
|
end
|
||||||
|
|
||||||
|
--- TODO: docs
|
||||||
|
---@param button MouseButton
|
||||||
|
function Window:begin_move(button)
|
||||||
|
self.config_client:unary_request(build_grpc_request_params("MoveGrab", { button = button }))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- TODO: docs
|
||||||
|
---@param button MouseButton
|
||||||
|
function Window:begin_resize(button)
|
||||||
|
self.config_client:unary_request(build_grpc_request_params("ResizeGrab", { button = button }))
|
||||||
|
end
|
||||||
|
|
||||||
|
---@class WindowRuleCondition
|
||||||
|
---@field any WindowRuleCondition[]?
|
||||||
|
---@field all WindowRuleCondition[]?
|
||||||
|
---@field classes string[]?
|
||||||
|
---@field titles string[]?
|
||||||
|
---@field tags TagHandle[]?
|
||||||
|
|
||||||
|
---@class WindowRule
|
||||||
|
---@field output OutputHandle?
|
||||||
|
---@field tags TagHandle[]?
|
||||||
|
---@field floating boolean?
|
||||||
|
---@field fullscreen_or_maximized FullscreenOrMaximized?
|
||||||
|
---@field x integer?
|
||||||
|
---@field y integer?
|
||||||
|
---@field width integer?
|
||||||
|
---@field height integer?
|
||||||
|
|
||||||
|
---@enum (key) FullscreenOrMaximized
|
||||||
|
local _fullscreen_or_maximized = {
|
||||||
|
neither = 1,
|
||||||
|
fullscreen = 2,
|
||||||
|
maximized = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
local _fullscreen_or_maximized_keys = {
|
||||||
|
[1] = "neither",
|
||||||
|
[2] = "fullscreen",
|
||||||
|
[3] = "maximized",
|
||||||
|
}
|
||||||
|
|
||||||
|
---@param rule { cond: WindowRuleCondition, rule: WindowRule }
|
||||||
|
function Window:add_window_rule(rule)
|
||||||
|
if rule.cond.tags then
|
||||||
|
local ids = {}
|
||||||
|
for _, tg in pairs(rule.cond.tags) do
|
||||||
|
table.insert(ids, tg.id)
|
||||||
|
end
|
||||||
|
rule.cond.tags = ids
|
||||||
|
end
|
||||||
|
|
||||||
|
if rule.rule.output then
|
||||||
|
rule.rule.output = rule.rule.output.name
|
||||||
|
end
|
||||||
|
|
||||||
|
if rule.rule.tags then
|
||||||
|
local ids = {}
|
||||||
|
for _, tg in pairs(rule.cond.tags) do
|
||||||
|
table.insert(ids, tg.id)
|
||||||
|
end
|
||||||
|
rule.cond.tags = ids
|
||||||
|
end
|
||||||
|
|
||||||
|
if rule.rule.fullscreen_or_maximized then
|
||||||
|
rule.rule.fullscreen_or_maximized = _fullscreen_or_maximized[rule.rule.fullscreen_or_maximized]
|
||||||
|
end
|
||||||
|
|
||||||
|
self.config_client:unary_request(build_grpc_request_params("AddWindowRule", {
|
||||||
|
cond = rule.cond,
|
||||||
|
rule = rule.rule,
|
||||||
|
}))
|
||||||
|
end
|
||||||
|
|
||||||
|
---Send a close request to this window.
|
||||||
|
function WindowHandle:close()
|
||||||
|
self.config_client:unary_request(build_grpc_request_params("Close", { window_id = self.id }))
|
||||||
|
end
|
||||||
|
|
||||||
|
---Set this window's location and/or size.
|
||||||
|
---
|
||||||
|
---@param geo { x: integer?, y: integer, width: integer?, height: integer? }
|
||||||
|
function WindowHandle:set_geometry(geo)
|
||||||
|
self.config_client:unary_request(build_grpc_request_params("SetGeometry", { window_id = self.id, geometry = geo }))
|
||||||
|
end
|
||||||
|
|
||||||
|
---Set this window to fullscreen or not.
|
||||||
|
---@param fullscreen boolean
|
||||||
|
function WindowHandle:set_fullscreen(fullscreen)
|
||||||
|
self.config_client:unary_request(
|
||||||
|
build_grpc_request_params("SetFullscreen", { window_id = self.id, set = fullscreen })
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
function WindowHandle:toggle_fullscreen()
|
||||||
|
self.config_client:unary_request(build_grpc_request_params("SetFullscreen", { window_id = self.id, toggle = {} }))
|
||||||
|
end
|
||||||
|
|
||||||
|
function WindowHandle:set_maximized(maximized)
|
||||||
|
self.config_client:unary_request(
|
||||||
|
build_grpc_request_params("SetMaximized", { window_id = self.id, set = maximized })
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
function WindowHandle:toggle_maximized()
|
||||||
|
self.config_client:unary_request(build_grpc_request_params("SetMaximized", { window_id = self.id, toggle = {} }))
|
||||||
|
end
|
||||||
|
|
||||||
|
function WindowHandle:set_floating(floating)
|
||||||
|
self.config_client:unary_request(build_grpc_request_params("SetFloating", { window_id = self.id, set = floating }))
|
||||||
|
end
|
||||||
|
|
||||||
|
function WindowHandle:toggle_floating()
|
||||||
|
self.config_client:unary_request(build_grpc_request_params("SetFloating", { window_id = self.id, toggle = {} }))
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param tag TagHandle
|
||||||
|
function WindowHandle:move_to_tag(tag)
|
||||||
|
self.config_client:unary_request(build_grpc_request_params("MoveToTag", { window_id = self.id, tag_id = tag.id }))
|
||||||
|
end
|
||||||
|
|
||||||
|
---Tag or untag the given tag on this window.
|
||||||
|
---@param tag TagHandle
|
||||||
|
---@param set boolean
|
||||||
|
function WindowHandle:set_tag(tag, set)
|
||||||
|
self.config_client:unary_request(
|
||||||
|
build_grpc_request_params("SetTag", { window_id = self.id, tag_id = tag.id, set = set })
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
---Toggle the given tag on this window.
|
||||||
|
---@param tag TagHandle
|
||||||
|
function WindowHandle:toggle_tag(tag)
|
||||||
|
self.config_client:unary_request(
|
||||||
|
build_grpc_request_params("SetTag", { window_id = self.id, tag_id = tag.id, toggle = {} })
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
---@class WindowProperties
|
||||||
|
---@field geometry { x: integer?, y: integer?, width: integer?, height: integer? }?
|
||||||
|
---@field class string?
|
||||||
|
---@field title string?
|
||||||
|
---@field focused boolean?
|
||||||
|
---@field floating boolean?
|
||||||
|
---@field fullscreen_or_maximized FullscreenOrMaximized?
|
||||||
|
|
||||||
|
---@return WindowProperties
|
||||||
|
function WindowHandle:props()
|
||||||
|
local response =
|
||||||
|
self.config_client:unary_request(build_grpc_request_params("GetProperties", { window_id = self.id }))
|
||||||
|
|
||||||
|
response.fullscreen_or_maximized = _fullscreen_or_maximized_keys[response.fullscreen_or_maximized]
|
||||||
|
|
||||||
|
return response
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param config_client Client
|
||||||
|
---@return Window
|
||||||
|
function window.new(config_client)
|
||||||
|
---@type Window
|
||||||
|
local self = {
|
||||||
|
config_client = config_client,
|
||||||
|
}
|
||||||
|
setmetatable(self, { __index = Window })
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
---Create a new `WindowHandle` from an id.
|
||||||
|
---@param config_client Client
|
||||||
|
---@param window_id integer
|
||||||
|
---@return WindowHandle
|
||||||
|
function window_handle.new(config_client, window_id)
|
||||||
|
---@type WindowHandle
|
||||||
|
local self = {
|
||||||
|
config_client = config_client,
|
||||||
|
id = window_id,
|
||||||
|
}
|
||||||
|
setmetatable(self, { __index = WindowHandle })
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param config_client Client
|
||||||
|
---@param window_ids integer[]
|
||||||
|
---
|
||||||
|
---@return WindowHandle[]
|
||||||
|
function window_handle.new_from_table(config_client, window_ids)
|
||||||
|
---@type WindowHandle[]
|
||||||
|
local handles = {}
|
||||||
|
|
||||||
|
for _, id in pairs(window_ids) do
|
||||||
|
table.insert(handles, window_handle.new(config_client, id))
|
||||||
|
end
|
||||||
|
|
||||||
|
return handles
|
||||||
|
end
|
||||||
|
|
||||||
|
return window
|
|
@ -1,10 +1,29 @@
|
||||||
local pinnacle = require("pinnacle")
|
require("pinnacle").setup(function(pinnacle)
|
||||||
|
local input = pinnacle.input
|
||||||
|
local process = pinnacle.process
|
||||||
|
local output = pinnacle.output
|
||||||
|
local tag = pinnacle.tag
|
||||||
|
local window = pinnacle.window
|
||||||
|
|
||||||
pinnacle.setup(function(pinnacle)
|
local mods = input.mod
|
||||||
pinnacle.input:set_keybind({ 1 }, "A", function()
|
|
||||||
print("hi from grpc keybind")
|
input:set_keybind({ mods.SHIFT }, "A", function()
|
||||||
|
process:spawn({ "alacritty" }, {
|
||||||
|
stdout = function(line)
|
||||||
|
print("stdout")
|
||||||
|
print(line)
|
||||||
|
end,
|
||||||
|
stderr = function(line)
|
||||||
|
print("stderr")
|
||||||
|
print(line)
|
||||||
|
end,
|
||||||
|
exit = function(code, msg)
|
||||||
|
print(code, msg)
|
||||||
|
end,
|
||||||
|
})
|
||||||
end)
|
end)
|
||||||
pinnacle.input:set_keybind({ 1 }, "Q", function()
|
|
||||||
|
input:set_keybind({ 1 }, "Q", function()
|
||||||
pinnacle:quit()
|
pinnacle:quit()
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -2,6 +2,8 @@ syntax = "proto2";
|
||||||
|
|
||||||
package pinnacle.process.v0alpha1;
|
package pinnacle.process.v0alpha1;
|
||||||
|
|
||||||
|
import "google/protobuf/empty.proto";
|
||||||
|
|
||||||
message SpawnRequest {
|
message SpawnRequest {
|
||||||
repeated string args = 1;
|
repeated string args = 1;
|
||||||
// Whether or not to spawn `args` if it is already running.
|
// Whether or not to spawn `args` if it is already running.
|
||||||
|
@ -18,6 +20,12 @@ message SpawnResponse {
|
||||||
optional string exit_message = 4;
|
optional string exit_message = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message SetEnvRequest {
|
||||||
|
optional string key = 1;
|
||||||
|
optional string value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
service ProcessService {
|
service ProcessService {
|
||||||
rpc Spawn(SpawnRequest) returns (stream SpawnResponse);
|
rpc Spawn(SpawnRequest) returns (stream SpawnResponse);
|
||||||
|
rpc SetEnv(SetEnvRequest) returns (google.protobuf.Empty);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ use pinnacle_api_defs::pinnacle::{
|
||||||
AccelProfile, ClickMethod, ScrollMethod, TapButtonMap,
|
AccelProfile, ClickMethod, ScrollMethod, TapButtonMap,
|
||||||
},
|
},
|
||||||
output::v0alpha1::{ConnectForAllRequest, ConnectForAllResponse, SetLocationRequest},
|
output::v0alpha1::{ConnectForAllRequest, ConnectForAllResponse, SetLocationRequest},
|
||||||
|
process::v0alpha1::SetEnvRequest,
|
||||||
tag::v0alpha1::{
|
tag::v0alpha1::{
|
||||||
AddRequest, AddResponse, RemoveRequest, SetActiveRequest, SetLayoutRequest, SwitchToRequest,
|
AddRequest, AddResponse, RemoveRequest, SetActiveRequest, SetLayoutRequest, SwitchToRequest,
|
||||||
},
|
},
|
||||||
|
@ -524,6 +525,33 @@ impl pinnacle::process::v0alpha1::process_service_server::ProcessService for Pro
|
||||||
|
|
||||||
Ok(Response::new(Box::pin(receiver_stream)))
|
Ok(Response::new(Box::pin(receiver_stream)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn set_env(&self, request: Request<SetEnvRequest>) -> Result<Response<()>, Status> {
|
||||||
|
let request = request.into_inner();
|
||||||
|
|
||||||
|
let key = request
|
||||||
|
.key
|
||||||
|
.ok_or_else(|| Status::invalid_argument("no key specified"))?;
|
||||||
|
let value = request
|
||||||
|
.value
|
||||||
|
.ok_or_else(|| Status::invalid_argument("no value specified"))?;
|
||||||
|
|
||||||
|
if key.is_empty() {
|
||||||
|
return Err(Status::invalid_argument("key was empty"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if key.contains(['\0', '=']) {
|
||||||
|
return Err(Status::invalid_argument("key contained NUL or ="));
|
||||||
|
}
|
||||||
|
|
||||||
|
if value.contains('\0') {
|
||||||
|
return Err(Status::invalid_argument("value contained NUL"));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::env::set_var(key, value);
|
||||||
|
|
||||||
|
Ok(Response::new(()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TagService {
|
pub struct TagService {
|
||||||
|
|
Loading…
Reference in a new issue