Simplify window in API

This commit is contained in:
Ottatop 2023-07-19 20:11:15 -05:00
parent 53f29086b6
commit fcc33c60f0
5 changed files with 112 additions and 189 deletions

View file

@ -66,14 +66,14 @@ require("pinnacle").setup(function(pinnacle)
-- Just testing stuff
input.keybind({ mod_key }, keys.h, function()
-- local win = window.get_focused()
-- if win ~= nil then
-- print("loc: " .. (win:loc() and win:loc().x or "nil") .. ", " .. (win:loc() and win:loc().y or "nil"))
-- print("size: " .. (win:size() and win:size().w or "nil") .. ", " .. (win:size() and win:size().h or "nil"))
-- print("class: " .. (win:class() or "nil"))
-- print("title: " .. (win:title() or "nil"))
-- print("float: " .. tostring(win:floating()))
-- end
local wins = window.get_all()
for _, win in pairs(wins) do
print("loc: " .. (win:loc() and win:loc().x or "nil") .. ", " .. (win:loc() and win:loc().y or "nil"))
print("size: " .. (win:size() and win:size().w or "nil") .. ", " .. (win:size() and win:size().h or "nil"))
print("class: " .. (win:class() or "nil"))
print("title: " .. (win:title() or "nil"))
print("float: " .. tostring(win:floating()))
end
local op = output.get_focused() --[[@as Output]]
print("res: " .. (op:res() and (op:res().w .. ", " .. op:res().h) or "nil"))

View file

@ -33,13 +33,7 @@
---@class _Request
--Windows
---@field GetWindowByAppId { app_id: string }
---@field GetWindowByTitle { title: string }
---@field GetWindowSize { window_id: WindowId }
---@field GetWindowLocation { window_id: WindowId }
---@field GetWindowFLoating { window_id: WindowId }
---@field GetWindowClass { window_id: WindowId }
---@field GetWindowTitle { window_id: WindowId }
---@field GetWindowProps { window_id: WindowId }
--Outputs
---@field GetOutputProps { output_name: string }
--Tags
@ -49,7 +43,7 @@
---@field GetTagActive { tag_id: TagId }
---@field GetTagName { tag_id: TagId }
---@alias Request _Request | "GetWindowByFocus" | "GetAllWindows" | "GetOutputs"
---@alias Request _Request | "GetWindows" | "GetOutputs"
---@class IncomingMsg
---@field CallCallback { callback_id: integer, args: Args }
@ -67,11 +61,7 @@
--Windows
---@field Window { window_id: WindowId|nil }
---@field Windows { window_ids: WindowId[] }
---@field WindowSize { size: integer[]? }
---@field WindowLocation { loc: integer[]? }
---@field WindowClass { class: string? }
---@field WindowTitle { title: string? }
---@field WindowFloating { floating: boolean? }
---@field WindowProps { size: integer[]?, loc: integer[]?, class: string?, title: string?, floating: boolean?, focused: boolean? }
--Outputs
---@field Output { output_name: OutputName? }
---@field Outputs { output_names: OutputName[] }

View file

@ -118,13 +118,13 @@ end
---@return { w: integer, h: integer }|nil size The size of the window, or nil if it doesn't exist.
function win:size()
SendRequest({
GetWindowSize = {
GetWindowProps = {
window_id = self.id,
},
})
local response = ReadMsg()
local size = response.RequestResponse.response.WindowSize.size
local size = response.RequestResponse.response.WindowProps.size
if size == nil then
return nil
else
@ -151,13 +151,13 @@ end
---@return { x: integer, y: integer }|nil loc The location of the window, or nil if it's not on-screen or alive.
function win:loc()
SendRequest({
GetWindowLocation = {
GetWindowProps = {
window_id = self.id,
},
})
local response = ReadMsg()
local loc = response.RequestResponse.response.WindowLocation.loc
local loc = response.RequestResponse.response.WindowProps.loc
if loc == nil then
return nil
else
@ -179,13 +179,13 @@ end
---@return string|nil class This window's class, or nil if it doesn't exist.
function win:class()
SendRequest({
GetWindowClass = {
GetWindowProps = {
window_id = self.id,
},
})
local response = ReadMsg()
local class = response.RequestResponse.response.WindowClass.class
local class = response.RequestResponse.response.WindowProps.class
return class
end
@ -200,13 +200,13 @@ end
---@return string|nil title This window's title, or nil if it doesn't exist.
function win:title()
SendRequest({
GetWindowTitle = {
GetWindowProps = {
window_id = self.id,
},
})
local response = ReadMsg()
local title = response.RequestResponse.response.WindowTitle.title
local title = response.RequestResponse.response.WindowProps.title
return title
end
@ -214,114 +214,120 @@ end
---
---### Example
---```lua
----- With Alacritty focused and floating...
---print(tostring(window.get_focused():floating()))
----- ...should print "true".
----- With the focused window floating...
---print(window.get_focused():floating())
----- ...should print `true`.
---```
---@return boolean|nil floating `true` if it's floating, `false` if it's tiled, or nil if it doesn't exist.
function win:floating()
SendRequest({
GetWindowFloating = {
GetWindowProps = {
window_id = self.id,
},
})
local response = ReadMsg()
local floating = response.RequestResponse.response.WindowFloating.floating
local floating = response.RequestResponse.response.WindowProps.floating
return floating
end
---Get whether or not this window is focused.
---
---### Example
---```lua
---print(window.get_focused():focused()) -- should print `true`.
---```
---@return boolean|nil floating `true` if it's floating, `false` if it's tiled, or nil if it doesn't exist.
function win:focused()
SendRequest({
GetWindowProps = {
window_id = self.id,
},
})
local response = ReadMsg()
local focused = response.RequestResponse.response.WindowProps.focused
return focused
end
-------------------------------------------------------------------
---@class WindowGlobal
local window = {}
---TODO: This function is not implemented yet.
---
---Get a window by its app id (aka its X11 class).
---@param app_id string The window's app id. For example, Alacritty's app id is "Alacritty".
---@return Window|nil
function window.get_by_app_id(app_id)
SendRequest({
GetWindowByAppId = {
app_id = app_id,
},
})
---Get all windows with the specified class (usually the name of the application).
---@param class string The class. For example, Alacritty's class is "Alacritty".
---@return Window[]
function window.get_by_class(class)
SendRequest("GetWindows")
local response = ReadMsg()
local window_id = response.RequestResponse.response.Window.window_id
local window_ids = response.RequestResponse.response.Windows.window_ids
if window_id == nil then
return nil
---@type Window[]
local windows = {}
for _, window_id in pairs(window_ids) do
local w = new_window({ id = window_id })
if w:class() == class then
table.insert(windows, w)
end
end
---@type Window
local wind = {
id = window_id,
}
return new_window(wind)
return windows
end
---TODO: This function is not implemented yet.
---
---Get a window by its title.
---@param title string The window's title.
---@return Window|nil
---Get all windows with the specified title.
---@param title string The title.
---@return Window[]
function window.get_by_title(title)
SendRequest({
GetWindowByTitle = {
title = title,
},
})
SendRequest("GetWindows")
local response = ReadMsg()
local window_id = response.RequestResponse.response.Window.window_id
local window_ids = response.RequestResponse.response.Windows.window_ids
if window_id == nil then
return nil
---@type Window[]
local windows = {}
for _, window_id in pairs(window_ids) do
local w = new_window({ id = window_id })
if w:title() == title then
table.insert(windows, w)
end
end
---@type Window
local wind = {
id = window_id,
}
return new_window(wind)
return windows
end
---Get the currently focused window.
---@return Window|nil
function window.get_focused()
SendRequest("GetWindowByFocus")
SendRequest("GetWindows")
local response = ReadMsg()
local window_id = response.RequestResponse.response.Window.window_id
local window_ids = response.RequestResponse.response.Windows.window_ids
if window_id == nil then
return nil
for _, window_id in pairs(window_ids) do
local w = new_window({ id = window_id })
if w:focused() then
return w
end
end
---@type Window
local wind = {
id = window_id,
}
return new_window(wind)
return nil
end
---Get all windows.
---@return Window[]
function window.get_all()
SendRequest("GetAllWindows")
SendRequest("GetWindows")
local window_ids = ReadMsg().RequestResponse.response.Windows.window_ids
---@type Window[]
local windows = {}
for i, window_id in ipairs(window_ids) do
windows[i] = new_window({ id = window_id })
for _, window_id in pairs(window_ids) do
table.insert(windows, new_window({ id = window_id }))
end
return windows
end

View file

@ -100,20 +100,13 @@ pub struct RequestId(pub u32);
/// Messages that require a server response, usually to provide some data.
pub enum Request {
// Windows
GetWindowByAppId { app_id: String },
GetWindowByTitle { title: String },
GetWindowByFocus,
GetAllWindows,
GetWindowSize { window_id: WindowId },
GetWindowLocation { window_id: WindowId },
GetWindowFloating { window_id: WindowId },
GetWindowClass { window_id: WindowId },
GetWindowTitle { window_id: WindowId },
GetWindows,
GetWindowProps { window_id: WindowId },
// Outputs
GetOutputs,
GetOutputProps { output_name: String },
// Tags
GetTagsByOutput { output_name: String },
GetTagsByOutput { output_name: String }, // TODO: move into props
GetTagsByName { tag_name: String },
GetTagOutput { tag_id: TagId },
GetTagActive { tag_id: TagId },
@ -202,20 +195,13 @@ pub enum RequestResponse {
Windows {
window_ids: Vec<WindowId>,
},
WindowSize {
WindowProps {
size: Option<(i32, i32)>,
},
WindowLocation {
loc: Option<(i32, i32)>,
},
WindowClass {
class: Option<String>,
},
WindowTitle {
title: Option<String>,
},
WindowFloating {
floating: Option<bool>,
focused: Option<bool>,
},
Output {
output_name: Option<String>,

View file

@ -353,32 +353,7 @@ impl<B: Backend> State<B> {
.expect("Stream doesn't exist");
let mut stream = stream.lock().expect("Couldn't lock stream");
match request {
Request::GetWindowByAppId { app_id: _ } => todo!(),
Request::GetWindowByTitle { title: _ } => todo!(),
Request::GetWindowByFocus => match self.focus_state.current_focus() {
Some(current_focus) => {
let window_id = current_focus.with_state(|state| state.id);
crate::api::send_to_client(
&mut stream,
&OutgoingMsg::RequestResponse {
response: RequestResponse::Window {
window_id: Some(window_id),
},
},
)
.expect("Send to client failed");
}
None => {
crate::api::send_to_client(
&mut stream,
&OutgoingMsg::RequestResponse {
response: RequestResponse::Window { window_id: None },
},
)
.expect("Send to client failed");
}
},
Request::GetAllWindows => {
Request::GetWindows => {
let window_ids = self
.windows
.iter()
@ -394,33 +369,16 @@ impl<B: Backend> State<B> {
)
.expect("Couldn't send to client");
}
Request::GetWindowSize { window_id } => {
let size = window_id
.window(self)
Request::GetWindowProps { window_id } => {
let window = window_id.window(self);
let size = window
.as_ref()
.map(|win| (win.geometry().size.w, win.geometry().size.h));
crate::api::send_to_client(
&mut stream,
&OutgoingMsg::RequestResponse {
response: RequestResponse::WindowSize { size },
},
)
.expect("failed to send to client");
}
Request::GetWindowLocation { window_id } => {
let loc = window_id
.window(self)
.and_then(|win| self.space.element_location(&win))
let loc = window
.as_ref()
.and_then(|win| self.space.element_location(win))
.map(|loc| (loc.x, loc.y));
crate::api::send_to_client(
&mut stream,
&OutgoingMsg::RequestResponse {
response: RequestResponse::WindowLocation { loc },
},
)
.expect("failed to send to client");
}
Request::GetWindowClass { window_id } => {
let class = window_id.window(self).and_then(|win| {
let (class, title) = window.as_ref().map_or((None, None), |win| {
compositor::with_states(win.toplevel().wl_surface(), |states| {
let lock = states
.data_map
@ -428,45 +386,28 @@ impl<B: Backend> State<B> {
.expect("XdgToplevelSurfaceData wasn't in surface's data map")
.lock()
.expect("failed to acquire lock");
lock.app_id.clone()
(lock.app_id.clone(), lock.title.clone())
})
});
crate::api::send_to_client(
&mut stream,
&OutgoingMsg::RequestResponse {
response: RequestResponse::WindowClass { class },
},
)
.expect("failed to send to client");
}
Request::GetWindowTitle { window_id } => {
let title = window_id.window(self).and_then(|win| {
compositor::with_states(win.toplevel().wl_surface(), |states| {
let lock = states
.data_map
.get::<XdgToplevelSurfaceData>()
.expect("XdgToplevelSurfaceData wasn't in surface's data map")
.lock()
.expect("failed to acquire lock");
lock.title.clone()
})
});
crate::api::send_to_client(
&mut stream,
&OutgoingMsg::RequestResponse {
response: RequestResponse::WindowTitle { title },
},
)
.expect("failed to send to client");
}
Request::GetWindowFloating { window_id } => {
let floating = window_id
.window(self)
let floating = window
.as_ref()
.map(|win| win.with_state(|state| state.floating.is_floating()));
let focused = window.as_ref().and_then(|win| {
self.focus_state
.current_focus() // TODO: actual focus
.map(|foc_win| win == &foc_win)
});
crate::api::send_to_client(
&mut stream,
&OutgoingMsg::RequestResponse {
response: RequestResponse::WindowFloating { floating },
response: RequestResponse::WindowProps {
size,
loc,
class,
title,
floating,
focused,
},
},
)
.expect("failed to send to client");