Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion api/lua/pinnacle/output.lua
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ end
local signal_name_to_SignalName = {
connect = "OutputConnect",
disconnect = "OutputDisconnect",
enable = "OutputEnable",
disable = "OutputDisable",
resize = "OutputResize",
move = "OutputMove",
pointer_enter = "OutputPointerEnter",
Expand All @@ -148,8 +150,10 @@ local signal_name_to_SignalName = {
}

---@class pinnacle.output.OutputSignal Signals related to output events.
---@field connect fun(output: pinnacle.output.OutputHandle)? An output was connected. FIXME: This currently does not fire for outputs that have been previously connected and disconnected.
---@field connect fun(output: pinnacle.output.OutputHandle)? An output was connected for the first time.
---@field disconnect fun(output: pinnacle.output.OutputHandle)? An output was disconnected.
---@field enable fun(output: pinnacle.output.OutputHandle)? An output was enabled.
---@field disable fun(output: pinnacle.output.OutputHandle)? An output was disabled.
---@field resize fun(output: pinnacle.output.OutputHandle, logical_width: integer, logical_height: integer)? An output's logical size changed.
---@field move fun(output: pinnacle.output.OutputHandle, x: integer, y: integer)? An output moved.
---@field pointer_enter fun(output: pinnacle.output.OutputHandle)? The pointer entered an output.
Expand Down
36 changes: 36 additions & 0 deletions api/lua/pinnacle/signal.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,22 @@ local signals = {
---@type fun(response: table)
on_response = nil,
},
OutputEnable = {
---@type grpc_client.h2.Stream?
sender = nil,
---@type { callback_id: integer, callback: fun(output: pinnacle.output.OutputHandle) }[]
callbacks = {},
---@type fun(response: table)
on_response = nil,
},
OutputDisable = {
---@type grpc_client.h2.Stream?
sender = nil,
---@type { callback_id: integer, callback: fun(output: pinnacle.output.OutputHandle) }[]
callbacks = {},
---@type fun(response: table)
on_response = nil,
},
OutputResize = {
---@type grpc_client.h2.Stream?
sender = nil,
Expand Down Expand Up @@ -169,6 +185,26 @@ signals.OutputDisconnect.on_response = function(response)
end
end

signals.OutputEnable.on_response = function(response)
---@diagnostic disable-next-line: invisible
local handle = require("pinnacle.output").handle.new(response.output_name)
local callbacks = require("pinnacle.util").deep_copy(signals.OutputEnable.callbacks)

for _, callback in ipairs(callbacks) do
protected_callback("OutputEnable", callback.callback, handle)
end
end

signals.OutputDisable.on_response = function(response)
---@diagnostic disable-next-line: invisible
local handle = require("pinnacle.output").handle.new(response.output_name)
local callbacks = require("pinnacle.util").deep_copy(signals.OutputDisable.callbacks)

for _, callback in ipairs(callbacks) do
protected_callback("OutputDisable", callback.callback, handle)
end
end

signals.OutputResize.on_response = function(response)
---@diagnostic disable-next-line: invisible
local handle = require("pinnacle.output").handle.new(response.output_name)
Expand Down
14 changes: 14 additions & 0 deletions api/protobuf/pinnacle/signal/v1/signal.proto
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ message OutputDisconnectRequest {
message OutputDisconnectResponse {
string output_name = 1;
}
message OutputEnableRequest {
StreamControl control = 1;
}
message OutputEnableResponse {
string output_name = 1;
}
message OutputDisableRequest {
StreamControl control = 1;
}
message OutputDisableResponse {
string output_name = 1;
}

message OutputResizeRequest {
StreamControl control = 1;
Expand Down Expand Up @@ -117,6 +129,8 @@ message InputDeviceAddedResponse {
service SignalService {
rpc OutputConnect(stream OutputConnectRequest) returns (stream OutputConnectResponse);
rpc OutputDisconnect(stream OutputDisconnectRequest) returns (stream OutputDisconnectResponse);
rpc OutputEnable(stream OutputEnableRequest) returns (stream OutputEnableResponse);
rpc OutputDisable(stream OutputDisableRequest) returns (stream OutputDisableResponse);
rpc OutputResize(stream OutputResizeRequest) returns (stream OutputResizeResponse);
rpc OutputMove(stream OutputMoveRequest) returns (stream OutputMoveResponse);
rpc OutputPointerEnter(stream OutputPointerEnterRequest) returns (stream OutputPointerEnterResponse);
Expand Down
2 changes: 2 additions & 0 deletions api/rust/src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ pub fn connect_signal(signal: OutputSignal) -> SignalHandle {
match signal {
OutputSignal::Connect(f) => signal_state.output_connect.add_callback(f),
OutputSignal::Disconnect(f) => signal_state.output_disconnect.add_callback(f),
OutputSignal::Enable(f) => signal_state.output_enable.add_callback(f),
OutputSignal::Disable(f) => signal_state.output_disable.add_callback(f),
OutputSignal::Resize(f) => signal_state.output_resize.add_callback(f),
OutputSignal::Move(f) => signal_state.output_move.add_callback(f),
OutputSignal::PointerEnter(f) => signal_state.output_pointer_enter.add_callback(f),
Expand Down
44 changes: 39 additions & 5 deletions api/rust/src/signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,10 @@ macro_rules! signals {
signals! {
/// Signals relating to output events.
OutputSignal => {
/// An output was connected.
/// An output was connected for the first time.
/// This will not trigger if the output was previously connected.
///
/// Callbacks receive the newly connected output.
///
/// FIXME: This will not run on outputs that have been previously connected.
/// | Tell the dev to fix this in the compositor.
OutputConnect = {
enum_name = Connect,
callback_type = SingleOutputFn,
Expand All @@ -140,7 +138,7 @@ signals! {
}
},
}
/// An output was connected.
/// An output was disconnected.
///
/// Callbacks receive the disconnected output.
OutputDisconnect = {
Expand All @@ -155,6 +153,36 @@ signals! {
}
},
}
/// An output was enabled.
///
/// Callbacks receive the enabled output.
OutputEnable = {
enum_name = Enable,
callback_type = SingleOutputFn,
client_request = output_enable,
on_response = |response, callbacks| {
let handle = OutputHandle { name: response.output_name };

for callback in callbacks {
callback(&handle);
}
},
}
/// An output was disabled.
///
/// Callbacks receive the disabled output.
OutputDisable = {
enum_name = Disable,
callback_type = SingleOutputFn,
client_request = output_disable,
on_response = |response, callbacks| {
let handle = OutputHandle { name: response.output_name };

for callback in callbacks {
callback(&handle);
}
},
}
/// An output's logical size changed.
///
/// Callbacks receive the output and new width and height.
Expand Down Expand Up @@ -335,6 +363,8 @@ pub(crate) type SingleWindowFn = Box<dyn FnMut(&WindowHandle) + Send + 'static>;
pub(crate) struct SignalState {
pub(crate) output_connect: SignalData<OutputConnect>,
pub(crate) output_disconnect: SignalData<OutputDisconnect>,
pub(crate) output_enable: SignalData<OutputEnable>,
pub(crate) output_disable: SignalData<OutputDisable>,
pub(crate) output_resize: SignalData<OutputResize>,
pub(crate) output_move: SignalData<OutputMove>,
pub(crate) output_pointer_enter: SignalData<OutputPointerEnter>,
Expand Down Expand Up @@ -362,6 +392,8 @@ impl SignalState {
Self {
output_connect: SignalData::new(),
output_disconnect: SignalData::new(),
output_enable: SignalData::new(),
output_disable: SignalData::new(),
output_resize: SignalData::new(),
output_move: SignalData::new(),
output_pointer_enter: SignalData::new(),
Expand All @@ -382,6 +414,8 @@ impl SignalState {
pub(crate) fn shutdown(&mut self) {
self.output_connect.reset();
self.output_disconnect.reset();
self.output_enable.reset();
self.output_disable.reset();
self.output_resize.reset();
self.output_move.reset();
self.output_pointer_enter.reset();
Expand Down
2 changes: 2 additions & 0 deletions pinnacle-api-defs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ pub mod pinnacle {
impl_signal_request!(
OutputConnectRequest,
OutputDisconnectRequest,
OutputEnableRequest,
OutputDisableRequest,
OutputResizeRequest,
OutputMoveRequest,
OutputPointerEnterRequest,
Expand Down
85 changes: 77 additions & 8 deletions src/api/signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ use pinnacle_api_defs::pinnacle::signal::{
self,
v1::{
InputDeviceAddedRequest, InputDeviceAddedResponse, OutputConnectRequest,
OutputConnectResponse, OutputDisconnectRequest, OutputDisconnectResponse,
OutputFocusedRequest, OutputFocusedResponse, OutputMoveRequest, OutputMoveResponse,
OutputPointerEnterRequest, OutputPointerEnterResponse, OutputPointerLeaveRequest,
OutputPointerLeaveResponse, OutputResizeRequest, OutputResizeResponse, SignalRequest,
StreamControl, TagActiveRequest, TagActiveResponse, WindowFocusedRequest,
WindowFocusedResponse, WindowPointerEnterRequest, WindowPointerEnterResponse,
WindowPointerLeaveRequest, WindowPointerLeaveResponse, WindowTitleChangedRequest,
WindowTitleChangedResponse,
OutputConnectResponse, OutputDisableRequest, OutputDisableResponse,
OutputDisconnectRequest, OutputDisconnectResponse, OutputEnableRequest,
OutputEnableResponse, OutputFocusedRequest, OutputFocusedResponse, OutputMoveRequest,
OutputMoveResponse, OutputPointerEnterRequest, OutputPointerEnterResponse,
OutputPointerLeaveRequest, OutputPointerLeaveResponse, OutputResizeRequest,
OutputResizeResponse, SignalRequest, StreamControl, TagActiveRequest, TagActiveResponse,
WindowFocusedRequest, WindowFocusedResponse, WindowPointerEnterRequest,
WindowPointerEnterResponse, WindowPointerLeaveRequest, WindowPointerLeaveResponse,
WindowTitleChangedRequest, WindowTitleChangedResponse,
},
};
use smithay::output::Output;
Expand All @@ -35,6 +36,8 @@ pub struct SignalState {
// Output
pub output_connect: OutputConnect,
pub output_disconnect: OutputDisconnect,
pub output_enable: OutputEnable,
pub output_disable: OutputDisable,
pub output_resize: OutputResize,
pub output_move: OutputMove,
pub output_pointer_enter: OutputPointerEnter,
Expand Down Expand Up @@ -136,6 +139,48 @@ impl Signal for OutputDisconnect {
}
}

#[derive(Debug, Default)]
pub struct OutputEnable {
v1: SignalData<signal::v1::OutputEnableResponse>,
}

impl Signal for OutputEnable {
type Args<'a> = &'a smithay::output::Output;

fn signal(&mut self, args: Self::Args<'_>) {
self.v1.signal(|buf| {
buf.push_back(signal::v1::OutputEnableResponse {
output_name: args.name(),
});
});
}

fn clear(&mut self) {
self.v1.instances.clear();
}
}

#[derive(Debug, Default)]
pub struct OutputDisable {
v1: SignalData<signal::v1::OutputDisableResponse>,
}

impl Signal for OutputDisable {
type Args<'a> = &'a smithay::output::Output;

fn signal(&mut self, args: Self::Args<'_>) {
self.v1.signal(|buf| {
buf.push_back(signal::v1::OutputDisableResponse {
output_name: args.name(),
});
});
}

fn clear(&mut self) {
self.v1.instances.clear();
}
}

#[derive(Debug, Default)]
pub struct OutputResize {
v1: SignalData<signal::v1::OutputResizeResponse>,
Expand Down Expand Up @@ -482,6 +527,8 @@ impl SignalService {
impl signal::v1::signal_service_server::SignalService for SignalService {
type OutputConnectStream = ResponseStream<OutputConnectResponse>;
type OutputDisconnectStream = ResponseStream<OutputDisconnectResponse>;
type OutputEnableStream = ResponseStream<OutputEnableResponse>;
type OutputDisableStream = ResponseStream<OutputDisableResponse>;
type OutputResizeStream = ResponseStream<OutputResizeResponse>;
type OutputMoveStream = ResponseStream<OutputMoveResponse>;
type OutputPointerEnterStream = ResponseStream<OutputPointerEnterResponse>;
Expand Down Expand Up @@ -519,6 +566,28 @@ impl signal::v1::signal_service_server::SignalService for SignalService {
})
}

async fn output_enable(
&self,
request: Request<Streaming<OutputEnableRequest>>,
) -> Result<Response<Self::OutputEnableStream>, Status> {
let in_stream = request.into_inner();

start_signal_stream(self.sender.clone(), in_stream, |state| {
&mut state.pinnacle.signal_state.output_enable.v1
})
}

async fn output_disable(
&self,
request: Request<Streaming<OutputDisableRequest>>,
) -> Result<Response<Self::OutputDisableStream>, Status> {
let in_stream = request.into_inner();

start_signal_stream(self.sender.clone(), in_stream, |state| {
&mut state.pinnacle.signal_state.output_disable.v1
})
}

async fn output_resize(
&self,
request: Request<Streaming<OutputResizeRequest>>,
Expand Down
7 changes: 7 additions & 0 deletions src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use tracing::{error, warn};
use wayland_backend::server::GlobalId;

use crate::{
api::signal::Signal,
output::OutputMode,
state::{Pinnacle, State, WithState},
};
Expand Down Expand Up @@ -187,6 +188,12 @@ impl State {
self.pinnacle
.output_power_management_state
.mode_set(output, powered);

if powered {
self.pinnacle.signal_state.output_enable.signal(output);
} else {
self.pinnacle.signal_state.output_disable.signal(output);
}
Comment on lines +192 to +196
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Powered != enable/disable, so this should be removed.

}
}

Expand Down
16 changes: 8 additions & 8 deletions src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ impl Pinnacle {
) {
let _span = tracy_client::span!("Pinnacle::change_output_state");

if let Some(_mode) = mode {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if let Some(_mode) = mode {
if mode.is_some() {

self.set_output_enabled(output, true);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of this being here. If the output was explicitly disabled I don't think I'd want a mode change to re-enable it; I'd expect it to stay disabled.

}

// Calculate the ratio that the pointer location was over the output's size
// so we can warp it if the output moves
let pointer_loc_ratio = self.seat.get_pointer().and_then(|ptr| {
Expand Down Expand Up @@ -308,23 +312,19 @@ impl Pinnacle {
self.space.map_output(output, output.current_location());

// Trigger the connect signal here for configs to reposition outputs
//
// TODO: Create a new output_disable/enable signal and trigger it here
// instead of connect and disconnect
if should_signal {
self.signal_state.output_connect.signal(output);
}

self.signal_state.output_enable.signal(output);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be in the if should_signal block above so it doesn't get triggered again if you enable an already enabled output.

} else {
if let Some(global) = output.with_state_mut(|state| state.enabled_global_id.take()) {
self.display_handle.remove_global::<State>(global);
}
self.space.unmap_output(output);

// Trigger the disconnect signal here for configs to reposition outputs
//
// TODO: Create a new output_disable/enable signal and trigger it here
// instead of connect and disconnect
self.signal_state.output_disconnect.signal(output);
// Trigger the disable signal here for configs to reposition outputs
self.signal_state.output_disable.signal(output);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be in the if block above for the same reason above.


self.gamma_control_manager_state.output_removed(output);

Expand Down
Loading