Add scale setting to API, fix fractional scaling

This commit is contained in:
Ottatop 2024-03-23 15:23:00 -05:00
parent 8d3bbf28f8
commit dfc7a1351e
5 changed files with 88 additions and 11 deletions

View file

@ -31,6 +31,13 @@ require("pinnacle").setup(function(Pinnacle)
-- Keybinds --
--------------------
Input.keybind({ mod_key }, "=", function()
Output.get_focused():increase_scale(0.25)
end)
Input.keybind({ mod_key }, "-", function()
Output.get_focused():decrease_scale(0.25)
end)
-- mod_key + alt + q = Quit Pinnacle
Input.keybind({ mod_key, "alt" }, "q", function()
Pinnacle.quit()

View file

@ -13,6 +13,7 @@ local service = prefix .. "OutputService"
local rpc_types = {
SetLocation = {},
SetMode = {},
SetScale = {},
ConnectForAll = {
response_type = "ConnectForAllResponse",
},
@ -389,6 +390,27 @@ function OutputHandle:set_mode(pixel_width, pixel_height, refresh_rate_millihz)
}))
end
---Set this output's scaling factor.
---
---@param scale number
function OutputHandle:set_scale(scale)
client.unary_request(build_grpc_request_params("SetScale", { output_name = self.name, absolute = scale }))
end
---Increase this output's scaling factor.
---
---@param increase_by number
function OutputHandle:increase_scale(increase_by)
client.unary_request(build_grpc_request_params("SetScale", { output_name = self.name, relative = increase_by }))
end
---Decrease this output's scaling factor.
---
---@param decrease_by number
function OutputHandle:decrease_scale(decrease_by)
client.unary_request(build_grpc_request_params("SetScale", { output_name = self.name, relative = -decrease_by }))
end
---@class Mode
---@field pixel_width integer
---@field pixel_height integer

View file

@ -24,6 +24,14 @@ message SetModeRequest {
optional uint32 refresh_rate_millihz = 4;
}
message SetScaleRequest {
optional string output_name = 1;
oneof absolute_or_relative {
float absolute = 2;
float relative = 3;
}
}
message GetRequest {}
message GetResponse {
repeated string output_names = 1;
@ -62,6 +70,7 @@ message GetPropertiesResponse {
service OutputService {
rpc SetLocation(SetLocationRequest) returns (google.protobuf.Empty);
rpc SetMode(SetModeRequest) returns (google.protobuf.Empty);
rpc SetScale(SetScaleRequest) returns (google.protobuf.Empty);
rpc Get(GetRequest) returns (GetResponse);
rpc GetProperties(GetPropertiesRequest) returns (GetPropertiesResponse);
}

View file

@ -14,7 +14,10 @@ use pinnacle_api_defs::pinnacle::{
},
output::{
self,
v0alpha1::{output_service_server, SetLocationRequest, SetModeRequest},
v0alpha1::{
output_service_server, set_scale_request::AbsoluteOrRelative, SetLocationRequest,
SetModeRequest, SetScaleRequest,
},
},
process::v0alpha1::{process_service_server, SetEnvRequest, SpawnRequest, SpawnResponse},
tag::{
@ -27,7 +30,9 @@ use pinnacle_api_defs::pinnacle::{
v0alpha1::{pinnacle_service_server, PingRequest, PingResponse, QuitRequest, SetOrToggle},
};
use smithay::{
desktop::layer_map_for_output,
input::keyboard::XkbConfig,
output::Scale,
reexports::{calloop, input as libinput},
};
use sysinfo::ProcessRefreshKind;
@ -977,6 +982,39 @@ impl output_service_server::OutputService for OutputService {
.await
}
async fn set_scale(&self, request: Request<SetScaleRequest>) -> Result<Response<()>, Status> {
let SetScaleRequest {
output_name: Some(output_name),
absolute_or_relative: Some(absolute_or_relative),
} = request.into_inner()
else {
return Err(Status::invalid_argument(
"output_name or absolute_or_relative were null",
));
};
run_unary_no_response(&self.sender, move |state| {
let Some(output) = OutputName(output_name).output(state) else {
return;
};
let mut current_scale = output.current_scale().fractional_scale();
match absolute_or_relative {
AbsoluteOrRelative::Absolute(abs) => current_scale = abs as f64,
AbsoluteOrRelative::Relative(rel) => current_scale += rel as f64,
}
current_scale = f64::max(current_scale, 0.25);
output.change_current_state(None, None, Some(Scale::Fractional(current_scale)), None);
layer_map_for_output(&output).arrange();
state.request_layout(&output);
state.schedule_render(&output);
})
.await
}
async fn get(
&self,
_request: Request<output::v0alpha1::GetRequest>,

View file

@ -106,12 +106,9 @@ where
.map(|geo| (surface, geo.loc))
})
.map(|(surface, loc)| {
let render_elements = surface.render_elements::<WaylandSurfaceRenderElement<R>>(
renderer,
loc.to_physical((scale.x.round() as i32, scale.y.round() as i32)),
scale,
1.0,
);
let loc = loc.to_physical_precise_round(scale);
let render_elements = surface
.render_elements::<WaylandSurfaceRenderElement<R>>(renderer, loc, scale, 1.0);
(surface.layer(), render_elements)
});
@ -150,8 +147,12 @@ where
.filter(|win| win.is_on_active_tag())
.map(|win| {
// subtract win.geometry().loc to align decorations correctly
let loc = (space.element_location(win).unwrap_or((0, 0).into()) - win.geometry().loc - output.current_location())
.to_physical((scale.x.round() as i32, scale.x.round() as i32));
let loc = (
space.element_location(win) .unwrap_or((0, 0).into())
- win.geometry().loc
- output.current_location()
)
.to_physical_precise_round(scale);
let elem_geo = space.element_geometry(win).map(|mut geo| {
geo.loc -= output.current_location();
@ -166,7 +167,7 @@ where
match rect {
Some(rect) => {
elems.into_iter().filter_map(|elem| {
CropRenderElement::from_element(elem, scale, rect.to_physical_precise_down(scale))
CropRenderElement::from_element(elem, scale, rect.to_physical_precise_round(scale))
}).map(TransformRenderElement::from).map(OutputRenderElements::from).collect::<Vec<_>>()
},
None => elems.into_iter().map(OutputRenderElements::from).collect(),
@ -243,7 +244,7 @@ where
};
let cursor_pos = pointer_location - output_geometry.loc.to_f64() - cursor_hotspot.to_f64();
let cursor_pos_scaled = cursor_pos.to_physical(scale).to_i32_round();
let cursor_pos_scaled = cursor_pos.to_physical_precise_round(scale);
// set cursor
if let Some(pointer_image) = pointer_image {