summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxVerevkin <maxxverrr@gmail.com>2023-02-04 22:15:55 +0200
committerMaxVerevkin <maxxverrr@gmail.com>2023-02-05 10:53:37 +0200
commitc6d9d21caf846db50f8eef82d450b97fd8c5e320 (patch)
treeacb0ddd68e433d3820180b582806dbe491f8aca1
parent2c6a8a3895158aca192712db8eb6d0dfe13a2998 (diff)
downloadi3bar-mango-c6d9d21caf846db50f8eef82d450b97fd8c5e320.tar.gz
implement fractional scaling support
-rw-r--r--Cargo.toml5
-rw-r--r--src/bar.rs47
-rw-r--r--src/protocol.rs2
-rw-r--r--src/state.rs41
4 files changed, 70 insertions, 25 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 729f9eb..d7455f4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,11 +16,14 @@ memchr = "2"
thiserror = "1.0.38"
wayrs-client = { version = "0.3", features = ["tokio"] }
-wayrs-protocols = { version = "0.3", features = ["wlr-layer-shell-unstable-v1"] }
wayrs-shm-alloc = "0.3"
xcursor = "0.3.4"
+[dependencies.wayrs-protocols]
+version = "0.3"
+features = ["wlr-layer-shell-unstable-v1", "viewporter", "fractional-scale-v1"]
+
[dependencies.tokio]
version = "1"
features = ["macros", "net", "rt", "sync", "io-util", "process"]
diff --git a/src/bar.rs b/src/bar.rs
index 2d29dca..3f3e958 100644
--- a/src/bar.rs
+++ b/src/bar.rs
@@ -23,9 +23,12 @@ pub struct Bar {
pub frame_cb: Option<WlCallback>,
pub width: u32,
pub height: u32,
- pub scale: i32,
+ pub scale: u32,
+ pub scale120: Option<u32>,
pub surface: WlSurface,
pub layer_surface: ZwlrLayerSurfaceV1,
+ pub viewport: WpViewport,
+ pub fractional_scale: Option<WpFractionalScaleV1>,
pub blocks_btns: ButtonManager<(Option<String>, Option<String>)>,
pub wm_info: WmInfo,
pub tags_btns: ButtonManager<String>,
@@ -84,17 +87,28 @@ impl Bar {
pub fn frame(&mut self, conn: &mut Connection<State>, ss: &mut SharedState) {
assert!(self.configured);
- let stride = 4 * self.width as i32;
- let width = self.width as i32;
- let height = self.height as i32;
- let width_f = width as f64;
- let height_f = height as f64;
+ let (pix_width, pix_height, scale_f) = match self.scale120 {
+ Some(scale120) => (
+ // rounding halfway away from zero
+ (self.width * scale120 + 60) / 120,
+ (self.height * scale120 + 60) / 120,
+ scale120 as f64 / 120.0,
+ ),
+ None => (
+ self.width * self.scale,
+ self.height * self.scale,
+ self.scale as f64,
+ ),
+ };
+
+ let width_f = self.width as f64;
+ let height_f = self.height as f64;
let (buffer, canvas) = ss.shm.alloc_buffer(
conn,
- width * self.scale,
- height * self.scale,
- stride * self.scale,
+ pix_width as i32,
+ pix_height as i32,
+ pix_width as i32 * 4,
wl_shm::Format::Argb8888,
);
@@ -102,16 +116,15 @@ impl Bar {
cairo::ImageSurface::create_for_data_unsafe(
canvas.as_mut_ptr(),
cairo::Format::ARgb32,
- width * self.scale,
- height * self.scale,
- stride * self.scale,
+ pix_width as i32,
+ pix_height as i32,
+ pix_width as i32 * 4,
)
.expect("cairo surface")
};
let cairo_ctx = cairo::Context::new(&cairo_surf).expect("cairo context");
- cairo_ctx.scale(self.scale as f64, self.scale as f64);
- self.surface.set_buffer_scale(conn, self.scale);
+ cairo_ctx.scale(scale_f, scale_f);
// Background
cairo_ctx.save().unwrap();
@@ -217,9 +230,11 @@ impl Bar {
height_f,
);
+ self.viewport
+ .set_destination(conn, self.width as i32, self.height as i32);
+
self.surface.attach(conn, buffer.wl, 0, 0);
- self.surface
- .damage_buffer(conn, 0, 0, width * self.scale, height * self.scale);
+ self.surface.damage(conn, 0, 0, i32::MAX, i32::MAX);
self.surface.commit(conn);
}
diff --git a/src/protocol.rs b/src/protocol.rs
index 6546743..e8f464e 100644
--- a/src/protocol.rs
+++ b/src/protocol.rs
@@ -2,6 +2,8 @@
use wayrs_client;
pub use wayrs_client::protocol::*;
+pub use wayrs_protocols::fractional_scale_v1::*;
+pub use wayrs_protocols::viewporter::*;
pub use wayrs_protocols::wlr_layer_shell_unstable_v1::*;
wayrs_client::scanner::generate!("protocols/river-status-unstable-v1.xml");
wayrs_client::scanner::generate!("protocols/river-control-unstable-v1.xml");
diff --git a/src/state.rs b/src/state.rs
index b4123d3..5a18a80 100644
--- a/src/state.rs
+++ b/src/state.rs
@@ -18,6 +18,8 @@ use crate::{
pub struct State {
wl_compositor: WlCompositor,
layer_shell: ZwlrLayerShellV1,
+ viewporter: WpViewporter,
+ fractional_scale_manager: Option<WpFractionalScaleManagerV1>,
pub seats: Vec<Seat>,
pub bars: Vec<Bar>,
@@ -64,12 +66,10 @@ impl State {
.is_ok();
let mut this = Self {
- wl_compositor: globals
- .bind(conn, 4..=5)
- .expect("could not bind wl_compositor"),
- layer_shell: globals
- .bind(conn, 1..=4)
- .expect("could not bind layer_shell"),
+ wl_compositor: globals.bind(conn, 4..=5).unwrap(),
+ layer_shell: globals.bind(conn, 1..=4).unwrap(),
+ viewporter: globals.bind(conn, 1..=1).unwrap(),
+ fractional_scale_manager: globals.bind(conn, 1..=1).ok(),
seats: Vec::new(),
bars: Vec::new(),
@@ -156,6 +156,10 @@ impl State {
let surface = self.wl_compositor.create_surface(conn);
+ let fractional_scale = self
+ .fractional_scale_manager
+ .map(|mgr| mgr.get_fractional_scale_with_cb(conn, surface, fractional_scale_cb));
+
let layer_surface = self.layer_shell.get_layer_surface_with_cb(
conn,
surface,
@@ -196,7 +200,10 @@ impl State {
width: 0,
height: self.shared_state.config.height,
scale: 1,
+ scale120: None,
surface,
+ viewport: self.viewporter.get_viewport(conn, surface),
+ fractional_scale,
layer_surface,
blocks_btns: Default::default(),
wm_info: Default::default(),
@@ -299,7 +306,7 @@ fn wl_output_cb(
.iter_mut()
.find(|bar| bar.output == output)
.unwrap();
- bar.scale = scale;
+ bar.scale = scale as u32;
// If bar is not configured yet, it is because we were waiting for the "scale" event
// before commiting the surface. Otherwise, there is no need to do any redrawing (we'll
// do that after "configure" event).
@@ -449,7 +456,7 @@ fn wl_pointer_cb(
.set_cursor(
conn,
"default",
- bar.scale as u32,
+ bar.scale,
args.serial,
&mut state.shared_state.shm,
seat.cursor_surface,
@@ -485,6 +492,24 @@ fn wl_pointer_cb(
}
}
+fn fractional_scale_cb(
+ conn: &mut Connection<State>,
+ state: &mut State,
+ fractional_scale: WpFractionalScaleV1,
+ event: wp_fractional_scale_v1::Event,
+) {
+ let wp_fractional_scale_v1::Event::PreferredScale(scale120) = event;
+ let bar = state
+ .bars
+ .iter_mut()
+ .find(|b| b.fractional_scale == Some(fractional_scale))
+ .unwrap();
+ if bar.scale120 != Some(scale120) {
+ bar.scale120 = Some(scale120);
+ bar.request_frame(conn);
+ }
+}
+
fn wm_info_cb(conn: &mut Connection<State>, state: &mut State, output: WlOutput, info: WmInfo) {
let bar = state.bars.iter_mut().find(|b| b.output == output).unwrap();
bar.set_wm_info(info);