mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2025-01-18 22:26:12 +01:00
Allo wmatching outputs by EDID serial
Note that EDID serials are not totally unique across all monitors. Also some monitors don't have an EDID serial number. Also this hasn't been tested yet
This commit is contained in:
parent
0284a70c10
commit
d2445afe10
5 changed files with 69 additions and 25 deletions
|
@ -167,6 +167,19 @@ function output.connect_for_all(callback)
|
|||
})
|
||||
end
|
||||
|
||||
---@param id_str string
|
||||
---@param op OutputHandle
|
||||
---
|
||||
---@return boolean
|
||||
local function output_id_matches(id_str, op)
|
||||
if id_str:match("^serial:") then
|
||||
local serial = tonumber(id_str:sub(8))
|
||||
return serial and serial == op:serial() or false
|
||||
else
|
||||
return id_str == op.name
|
||||
end
|
||||
end
|
||||
|
||||
---@class OutputSetup
|
||||
---@field filter (fun(output: OutputHandle): boolean)?
|
||||
---@field mode Mode?
|
||||
|
@ -242,7 +255,9 @@ function output.setup(setups)
|
|||
if op_id:match("^%d+:") then
|
||||
---@type string
|
||||
local index = op_id:match("^%d+")
|
||||
---@diagnostic disable-next-line: redefined-local
|
||||
local op_id = op_id:sub(index:len() + 2)
|
||||
---@diagnostic disable-next-line: redefined-local
|
||||
local index = tonumber(index)
|
||||
|
||||
---@cast index number
|
||||
|
@ -280,7 +295,7 @@ function output.setup(setups)
|
|||
---@param op OutputHandle
|
||||
local function apply_setups(op)
|
||||
for _, op_setup in ipairs(op_setups) do
|
||||
if op_setup[1] == op.name or op_setup[1] == "*" then
|
||||
if output_id_matches(op_setup[1], op) or op_setup[1] == "*" then
|
||||
local setup = op_setup.setup
|
||||
|
||||
if setup.filter and not setup.filter(op) then
|
||||
|
@ -380,7 +395,9 @@ function output.setup_locs(update_locs_on, locs)
|
|||
if op_id:match("^%d+:") then
|
||||
---@type string
|
||||
local index = op_id:match("^%d+")
|
||||
---@diagnostic disable-next-line: redefined-local
|
||||
local op_id = op_id:sub(index:len() + 2)
|
||||
---@diagnostic disable-next-line: redefined-local
|
||||
local index = tonumber(index)
|
||||
|
||||
---@cast index number
|
||||
|
@ -417,7 +434,7 @@ function output.setup_locs(update_locs_on, locs)
|
|||
---@diagnostic disable-next-line: redefined-local
|
||||
for _, setup in ipairs(setups) do
|
||||
for _, op in ipairs(outputs) do
|
||||
if op.name == setup[1] then
|
||||
if output_id_matches(setup[1], op) then
|
||||
if type(setup.loc[1]) == "number" then
|
||||
local loc = { x = setup.loc[1], y = setup.loc[2] }
|
||||
op:set_location(loc)
|
||||
|
@ -445,7 +462,7 @@ function output.setup_locs(update_locs_on, locs)
|
|||
end
|
||||
end
|
||||
|
||||
if op.name ~= setup[1] or type(setup.loc[1]) == "number" then
|
||||
if not output_id_matches(setup[1], op) or type(setup.loc[1]) == "number" then
|
||||
goto continue
|
||||
end
|
||||
|
||||
|
@ -1028,7 +1045,7 @@ function OutputHandle:transform()
|
|||
return self:props().transform
|
||||
end
|
||||
|
||||
---Get this output's serial.
|
||||
---Get this output's EDID serial number.
|
||||
---
|
||||
---Shorthand for `handle:props().serial`.
|
||||
---
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
//! This module provides [`Output`], which allows you to get [`OutputHandle`]s for different
|
||||
//! connected monitors and set them up.
|
||||
|
||||
use std::sync::OnceLock;
|
||||
use std::{num::NonZeroU32, sync::OnceLock};
|
||||
|
||||
use futures::FutureExt;
|
||||
use pinnacle_api_defs::pinnacle::output::{
|
||||
|
@ -516,7 +516,13 @@ pub enum OutputLoc {
|
|||
pub enum OutputId {
|
||||
/// Identify using the output's name.
|
||||
Name(String),
|
||||
// TODO: serial
|
||||
/// Identify using the output's EDID serial number.
|
||||
///
|
||||
/// Note: some displays (like laptop screens) don't have a serial number, in which case this won't match it.
|
||||
/// Additionally the Rust API assumes monitor serial numbers are unique.
|
||||
/// If you're unlucky enough to have two monitors with the same serial number,
|
||||
/// use [`OutputId::Name`] instead.
|
||||
Serial(NonZeroU32),
|
||||
}
|
||||
|
||||
impl OutputId {
|
||||
|
@ -532,6 +538,7 @@ impl OutputId {
|
|||
pub fn matches(&self, output: &OutputHandle) -> bool {
|
||||
match self {
|
||||
OutputId::Name(name) => name == output.name(),
|
||||
OutputId::Serial(serial) => Some(serial.get()) == output.serial(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1111,6 +1118,30 @@ impl OutputHandle {
|
|||
self.props_async().await.scale
|
||||
}
|
||||
|
||||
/// Get this output's transform.
|
||||
///
|
||||
/// Shorthand for `self.props().transform`
|
||||
pub fn transform(&self) -> Option<Transform> {
|
||||
self.props().transform
|
||||
}
|
||||
|
||||
/// The async version of [`OutputHandle::transform`].
|
||||
pub async fn transform_async(&self) -> Option<Transform> {
|
||||
self.props_async().await.transform
|
||||
}
|
||||
|
||||
/// Get this output's EDID serial number.
|
||||
///
|
||||
/// Shorthand for `self.props().serial`
|
||||
pub fn serial(&self) -> Option<u32> {
|
||||
self.props().serial
|
||||
}
|
||||
|
||||
/// The async version of [`OutputHandle::serial`].
|
||||
pub async fn serial_async(&self) -> Option<u32> {
|
||||
self.props_async().await.serial
|
||||
}
|
||||
|
||||
/// Get this output's unique name (the name of its connector).
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
use std::{num::NonZeroU32, sync::RwLock};
|
||||
use std::{cell::RefCell, num::NonZeroU32};
|
||||
|
||||
use pinnacle_api_defs::pinnacle::signal::v0alpha1::{OutputMoveResponse, OutputResizeResponse};
|
||||
use smithay::{
|
||||
|
@ -53,9 +53,9 @@ impl WithState for Output {
|
|||
{
|
||||
let state = self
|
||||
.user_data()
|
||||
.get_or_insert_threadsafe(RwLock::<Self::State>::default);
|
||||
.get_or_insert(RefCell::<Self::State>::default);
|
||||
|
||||
func(&state.read().expect("with_state already locked"))
|
||||
func(&state.borrow())
|
||||
}
|
||||
|
||||
fn with_state_mut<F, T>(&self, func: F) -> T
|
||||
|
@ -64,9 +64,9 @@ impl WithState for Output {
|
|||
{
|
||||
let state = self
|
||||
.user_data()
|
||||
.get_or_insert_threadsafe(RwLock::<Self::State>::default);
|
||||
.get_or_insert(RefCell::<Self::State>::default);
|
||||
|
||||
func(&mut state.write().expect("with_state already locked"))
|
||||
func(&mut state.borrow_mut())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
14
src/state.rs
14
src/state.rs
|
@ -40,11 +40,7 @@ use smithay::{
|
|||
},
|
||||
xwayland::{X11Wm, XWayland, XWaylandEvent},
|
||||
};
|
||||
use std::{
|
||||
path::PathBuf,
|
||||
sync::{Arc, RwLock},
|
||||
time::Duration,
|
||||
};
|
||||
use std::{cell::RefCell, path::PathBuf, sync::Arc, time::Duration};
|
||||
use sysinfo::{ProcessRefreshKind, RefreshKind};
|
||||
use tracing::{error, info};
|
||||
use xdg::BaseDirectories;
|
||||
|
@ -382,9 +378,9 @@ impl WithState for WlSurface {
|
|||
compositor::with_states(self, |states| {
|
||||
let state = states
|
||||
.data_map
|
||||
.get_or_insert_threadsafe(RwLock::<Self::State>::default);
|
||||
.get_or_insert(RefCell::<Self::State>::default);
|
||||
|
||||
func(&state.read().expect("with_state already locked"))
|
||||
func(&state.borrow())
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -395,9 +391,9 @@ impl WithState for WlSurface {
|
|||
compositor::with_states(self, |states| {
|
||||
let state = states
|
||||
.data_map
|
||||
.get_or_insert_threadsafe(RwLock::<Self::State>::default);
|
||||
.get_or_insert(RefCell::<Self::State>::default);
|
||||
|
||||
func(&mut state.write().expect("with_state already locked"))
|
||||
func(&mut state.borrow_mut())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
pub mod rules;
|
||||
|
||||
use std::{ops::Deref, sync::RwLock};
|
||||
use std::{cell::RefCell, ops::Deref};
|
||||
|
||||
use smithay::{
|
||||
desktop::{space::SpaceElement, Window, WindowSurface},
|
||||
|
@ -192,9 +192,9 @@ impl WithState for WindowElement {
|
|||
{
|
||||
let state = self
|
||||
.user_data()
|
||||
.get_or_insert_threadsafe(|| RwLock::new(WindowElementState::new()));
|
||||
.get_or_insert(|| RefCell::new(WindowElementState::new()));
|
||||
|
||||
func(&state.read().expect("with_state already locked"))
|
||||
func(&state.borrow())
|
||||
}
|
||||
|
||||
fn with_state_mut<F, T>(&self, func: F) -> T
|
||||
|
@ -203,9 +203,9 @@ impl WithState for WindowElement {
|
|||
{
|
||||
let state = self
|
||||
.user_data()
|
||||
.get_or_insert(|| RwLock::new(WindowElementState::new()));
|
||||
.get_or_insert(|| RefCell::new(WindowElementState::new()));
|
||||
|
||||
func(&mut state.write().expect("with_state already locked"))
|
||||
func(&mut state.borrow_mut())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue