mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-23 13:51:30 +11:00
On Wayland, add support for fractional scaling
This adds support for the fractional scaling on Wayland via the wp-fractional-scale protocol. Co-authored-by: Julian Orth <ju.orth@gmail.com>
This commit is contained in:
parent
1886949efe
commit
de782504ab
|
@ -59,6 +59,7 @@ And please only add new entries to the top of this list, right below the `# Unre
|
||||||
- On X11, added `drag_resize_window` method.
|
- On X11, added `drag_resize_window` method.
|
||||||
- Added `Window::set_transparent` to provide a hint about transparency of the window on Wayland and macOS.
|
- Added `Window::set_transparent` to provide a hint about transparency of the window on Wayland and macOS.
|
||||||
- On macOS, fix the mouse buttons other than left/right/middle being reported as middle.
|
- On macOS, fix the mouse buttons other than left/right/middle being reported as middle.
|
||||||
|
- On Wayland, support fractional scaling via the wp-fractional-scale protocol.
|
||||||
|
|
||||||
# 0.27.5
|
# 0.27.5
|
||||||
|
|
||||||
|
|
10
Cargo.toml
10
Cargo.toml
|
@ -37,7 +37,7 @@ rustdoc-args = ["--cfg", "docsrs"]
|
||||||
[features]
|
[features]
|
||||||
default = ["x11", "wayland", "wayland-dlopen", "wayland-csd-adwaita"]
|
default = ["x11", "wayland", "wayland-dlopen", "wayland-csd-adwaita"]
|
||||||
x11 = ["x11-dl", "mio", "percent-encoding"]
|
x11 = ["x11-dl", "mio", "percent-encoding"]
|
||||||
wayland = ["wayland-client", "wayland-protocols", "sctk"]
|
wayland = ["wayland-client", "wayland-protocols", "sctk", "wayland-commons"]
|
||||||
wayland-dlopen = ["sctk/dlopen", "wayland-client/dlopen"]
|
wayland-dlopen = ["sctk/dlopen", "wayland-client/dlopen"]
|
||||||
wayland-csd-adwaita = ["sctk-adwaita", "sctk-adwaita/ab_glyph"]
|
wayland-csd-adwaita = ["sctk-adwaita", "sctk-adwaita/ab_glyph"]
|
||||||
wayland-csd-adwaita-crossfont = ["sctk-adwaita", "sctk-adwaita/crossfont"]
|
wayland-csd-adwaita-crossfont = ["sctk-adwaita", "sctk-adwaita/crossfont"]
|
||||||
|
@ -109,14 +109,18 @@ mio = { version = "0.8", features = ["os-ext"], optional = true }
|
||||||
percent-encoding = { version = "2.0", optional = true }
|
percent-encoding = { version = "2.0", optional = true }
|
||||||
sctk = { package = "smithay-client-toolkit", version = "0.16.0", default_features = false, features = ["calloop"], optional = true }
|
sctk = { package = "smithay-client-toolkit", version = "0.16.0", default_features = false, features = ["calloop"], optional = true }
|
||||||
sctk-adwaita = { version = "0.5.1", default_features = false, optional = true }
|
sctk-adwaita = { version = "0.5.1", default_features = false, optional = true }
|
||||||
wayland-client = { version = "0.29.4", default_features = false, features = ["use_system_lib"], optional = true }
|
wayland-client = { version = "0.29.5", default_features = false, features = ["use_system_lib"], optional = true }
|
||||||
wayland-protocols = { version = "0.29.4", features = [ "staging_protocols"], optional = true }
|
wayland-protocols = { version = "0.29.5", features = [ "staging_protocols"], optional = true }
|
||||||
|
wayland-commons = { version = "0.29.5", optional = true }
|
||||||
x11-dl = { version = "2.18.5", optional = true }
|
x11-dl = { version = "2.18.5", optional = true }
|
||||||
|
|
||||||
[target.'cfg(target_os = "redox")'.dependencies]
|
[target.'cfg(target_os = "redox")'.dependencies]
|
||||||
orbclient = { version = "0.3.42", default-features = false }
|
orbclient = { version = "0.3.42", default-features = false }
|
||||||
redox_syscall = "0.3"
|
redox_syscall = "0.3"
|
||||||
|
|
||||||
|
[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.build-dependencies]
|
||||||
|
wayland-scanner = "0.29.5"
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies.web_sys]
|
[target.'cfg(target_arch = "wasm32")'.dependencies.web_sys]
|
||||||
package = "web-sys"
|
package = "web-sys"
|
||||||
version = "0.3.22"
|
version = "0.3.22"
|
||||||
|
|
41
build.rs
41
build.rs
|
@ -1,8 +1,34 @@
|
||||||
use cfg_aliases::cfg_aliases;
|
use cfg_aliases::cfg_aliases;
|
||||||
|
|
||||||
|
#[cfg(all(
|
||||||
|
any(
|
||||||
|
target_os = "linux",
|
||||||
|
target_os = "dragonfly",
|
||||||
|
target_os = "freebsd",
|
||||||
|
target_os = "openbsd",
|
||||||
|
target_os = "netbsd",
|
||||||
|
),
|
||||||
|
feature = "wayland",
|
||||||
|
))]
|
||||||
|
mod wayland {
|
||||||
|
use std::env;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use wayland_scanner::Side;
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let mut path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||||
|
path.push("fractional_scale_v1.rs");
|
||||||
|
wayland_scanner::generate_code(
|
||||||
|
"wayland_protocols/fractional-scale-v1.xml",
|
||||||
|
&path,
|
||||||
|
Side::Client,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// The script doesn't depend on our code
|
// The script doesn't depend on our code
|
||||||
println!("cargo:rerun-if-changed=build.rs");
|
println!("cargo:rerun-if-changed=build.rs:wayland_protocols");
|
||||||
// Setup cfg aliases
|
// Setup cfg aliases
|
||||||
cfg_aliases! {
|
cfg_aliases! {
|
||||||
// Systems.
|
// Systems.
|
||||||
|
@ -20,4 +46,17 @@ fn main() {
|
||||||
wayland_platform: { all(feature = "wayland", free_unix, not(wasm), not(redox)) },
|
wayland_platform: { all(feature = "wayland", free_unix, not(wasm), not(redox)) },
|
||||||
orbital_platform: { redox },
|
orbital_platform: { redox },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX aliases are not available for the build script itself.
|
||||||
|
#[cfg(all(
|
||||||
|
any(
|
||||||
|
target_os = "linux",
|
||||||
|
target_os = "dragonfly",
|
||||||
|
target_os = "freebsd",
|
||||||
|
target_os = "openbsd",
|
||||||
|
target_os = "netbsd",
|
||||||
|
),
|
||||||
|
feature = "wayland",
|
||||||
|
))]
|
||||||
|
wayland::main();
|
||||||
}
|
}
|
||||||
|
|
|
@ -441,7 +441,7 @@ impl Window {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn scale_factor(&self) -> f64 {
|
pub fn scale_factor(&self) -> f64 {
|
||||||
x11_or_wayland!(match self; Window(w) => w.scale_factor() as _)
|
x11_or_wayland!(match self; Window(w) => w.scale_factor())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -14,6 +14,7 @@ use sctk::reexports::protocols::unstable::relative_pointer::v1::client::zwp_rela
|
||||||
use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_pointer_constraints_v1::ZwpPointerConstraintsV1;
|
use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_pointer_constraints_v1::ZwpPointerConstraintsV1;
|
||||||
use sctk::reexports::protocols::unstable::text_input::v3::client::zwp_text_input_manager_v3::ZwpTextInputManagerV3;
|
use sctk::reexports::protocols::unstable::text_input::v3::client::zwp_text_input_manager_v3::ZwpTextInputManagerV3;
|
||||||
use sctk::reexports::protocols::staging::xdg_activation::v1::client::xdg_activation_v1::XdgActivationV1;
|
use sctk::reexports::protocols::staging::xdg_activation::v1::client::xdg_activation_v1::XdgActivationV1;
|
||||||
|
use sctk::reexports::protocols::viewporter::client::wp_viewporter::WpViewporter;
|
||||||
|
|
||||||
use sctk::environment::{Environment, SimpleGlobal};
|
use sctk::environment::{Environment, SimpleGlobal};
|
||||||
use sctk::output::{OutputHandler, OutputHandling, OutputInfo, OutputStatusListener};
|
use sctk::output::{OutputHandler, OutputHandling, OutputInfo, OutputStatusListener};
|
||||||
|
@ -21,6 +22,8 @@ use sctk::seat::{SeatData, SeatHandler, SeatHandling, SeatListener};
|
||||||
use sctk::shell::{Shell, ShellHandler, ShellHandling};
|
use sctk::shell::{Shell, ShellHandler, ShellHandling};
|
||||||
use sctk::shm::ShmHandler;
|
use sctk::shm::ShmHandler;
|
||||||
|
|
||||||
|
use crate::platform_impl::wayland::protocols::wp_fractional_scale_manager_v1::WpFractionalScaleManagerV1;
|
||||||
|
|
||||||
/// Set of extra features that are supported by the compositor.
|
/// Set of extra features that are supported by the compositor.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct WindowingFeatures {
|
pub struct WindowingFeatures {
|
||||||
|
@ -61,6 +64,8 @@ sctk::environment!(WinitEnv,
|
||||||
ZwpPointerConstraintsV1 => pointer_constraints,
|
ZwpPointerConstraintsV1 => pointer_constraints,
|
||||||
ZwpTextInputManagerV3 => text_input_manager,
|
ZwpTextInputManagerV3 => text_input_manager,
|
||||||
XdgActivationV1 => xdg_activation,
|
XdgActivationV1 => xdg_activation,
|
||||||
|
WpFractionalScaleManagerV1 => fractional_scale_manager,
|
||||||
|
WpViewporter => viewporter,
|
||||||
],
|
],
|
||||||
multis = [
|
multis = [
|
||||||
WlSeat => seats,
|
WlSeat => seats,
|
||||||
|
@ -91,6 +96,10 @@ pub struct WinitEnv {
|
||||||
decoration_manager: SimpleGlobal<ZxdgDecorationManagerV1>,
|
decoration_manager: SimpleGlobal<ZxdgDecorationManagerV1>,
|
||||||
|
|
||||||
xdg_activation: SimpleGlobal<XdgActivationV1>,
|
xdg_activation: SimpleGlobal<XdgActivationV1>,
|
||||||
|
|
||||||
|
fractional_scale_manager: SimpleGlobal<WpFractionalScaleManagerV1>,
|
||||||
|
|
||||||
|
viewporter: SimpleGlobal<WpViewporter>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WinitEnv {
|
impl WinitEnv {
|
||||||
|
@ -125,6 +134,12 @@ impl WinitEnv {
|
||||||
// Surface activation.
|
// Surface activation.
|
||||||
let xdg_activation = SimpleGlobal::new();
|
let xdg_activation = SimpleGlobal::new();
|
||||||
|
|
||||||
|
// Fractional surface scaling.
|
||||||
|
let fractional_scale_manager = SimpleGlobal::new();
|
||||||
|
|
||||||
|
// Surface resizing (used for fractional scaling).
|
||||||
|
let viewporter = SimpleGlobal::new();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
seats,
|
seats,
|
||||||
outputs,
|
outputs,
|
||||||
|
@ -137,6 +152,8 @@ impl WinitEnv {
|
||||||
pointer_constraints,
|
pointer_constraints,
|
||||||
text_input_manager,
|
text_input_manager,
|
||||||
xdg_activation,
|
xdg_activation,
|
||||||
|
fractional_scale_manager,
|
||||||
|
viewporter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -374,10 +374,11 @@ impl<T: 'static> EventLoop<T> {
|
||||||
});
|
});
|
||||||
|
|
||||||
for (window_id, window_compositor_update) in window_compositor_updates.iter_mut() {
|
for (window_id, window_compositor_update) in window_compositor_updates.iter_mut() {
|
||||||
if let Some(scale_factor) = window_compositor_update.scale_factor.map(|f| f as f64)
|
if let Some(scale_factor) = window_compositor_update.scale_factor {
|
||||||
{
|
|
||||||
let mut physical_size = self.with_state(|state| {
|
let mut physical_size = self.with_state(|state| {
|
||||||
let window_handle = state.window_map.get(window_id).unwrap();
|
let window_handle = state.window_map.get(window_id).unwrap();
|
||||||
|
*window_handle.scale_factor.lock().unwrap() = scale_factor;
|
||||||
|
|
||||||
let mut size = window_handle.size.lock().unwrap();
|
let mut size = window_handle.size.lock().unwrap();
|
||||||
|
|
||||||
// Update the new logical size if it was changed.
|
// Update the new logical size if it was changed.
|
||||||
|
@ -409,6 +410,15 @@ impl<T: 'static> EventLoop<T> {
|
||||||
if let Some(size) = window_compositor_update.size.take() {
|
if let Some(size) = window_compositor_update.size.take() {
|
||||||
let physical_size = self.with_state(|state| {
|
let physical_size = self.with_state(|state| {
|
||||||
let window_handle = state.window_map.get_mut(window_id).unwrap();
|
let window_handle = state.window_map.get_mut(window_id).unwrap();
|
||||||
|
|
||||||
|
if let Some(fs_state) = window_handle.fractional_scaling_state.as_ref() {
|
||||||
|
// If we have a viewport then we support fractional scaling. As per the
|
||||||
|
// protocol, we have to set the viewport size of the size prior scaling.
|
||||||
|
fs_state
|
||||||
|
.viewport
|
||||||
|
.set_destination(size.width as _, size.height as _);
|
||||||
|
}
|
||||||
|
|
||||||
let mut window_size = window_handle.size.lock().unwrap();
|
let mut window_size = window_handle.size.lock().unwrap();
|
||||||
|
|
||||||
// Always issue resize event on scale factor change.
|
// Always issue resize event on scale factor change.
|
||||||
|
@ -419,9 +429,8 @@ impl<T: 'static> EventLoop<T> {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
*window_size = size;
|
*window_size = size;
|
||||||
let scale_factor =
|
let scale_factor = window_handle.scale_factor();
|
||||||
sctk::get_surface_scale_factor(window_handle.window.surface());
|
let physical_size = size.to_physical(scale_factor);
|
||||||
let physical_size = size.to_physical(scale_factor as f64);
|
|
||||||
Some(physical_size)
|
Some(physical_size)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ pub use window::Window;
|
||||||
mod env;
|
mod env;
|
||||||
mod event_loop;
|
mod event_loop;
|
||||||
mod output;
|
mod output;
|
||||||
|
mod protocols;
|
||||||
mod seat;
|
mod seat;
|
||||||
mod window;
|
mod window;
|
||||||
|
|
||||||
|
|
13
src/platform_impl/linux/wayland/protocols.rs
Normal file
13
src/platform_impl/linux/wayland/protocols.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#![allow(dead_code, non_camel_case_types, unused_unsafe, unused_variables)]
|
||||||
|
#![allow(non_upper_case_globals, non_snake_case, unused_imports)]
|
||||||
|
#![allow(missing_docs, clippy::all)]
|
||||||
|
|
||||||
|
use wayland_client::protocol::wl_surface;
|
||||||
|
use wayland_client::sys;
|
||||||
|
use wayland_client::{AnonymousObject, Attached, Main, Proxy, ProxyMap};
|
||||||
|
use wayland_commons::map::{Object, ObjectMetadata};
|
||||||
|
use wayland_commons::smallvec;
|
||||||
|
use wayland_commons::wire::{Argument, ArgumentType, Message, MessageDesc};
|
||||||
|
use wayland_commons::{Interface, MessageGroup};
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/fractional_scale_v1.rs"));
|
|
@ -53,7 +53,7 @@ pub(super) fn handle_pointer(
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let scale_factor = sctk::get_surface_scale_factor(&surface) as f64;
|
let scale_factor = window_handle.scale_factor();
|
||||||
pointer_data.surface = Some(surface);
|
pointer_data.surface = Some(surface);
|
||||||
|
|
||||||
// Notify window that pointer entered the surface.
|
// Notify window that pointer entered the surface.
|
||||||
|
@ -133,8 +133,12 @@ pub(super) fn handle_pointer(
|
||||||
};
|
};
|
||||||
|
|
||||||
let window_id = wayland::make_wid(surface);
|
let window_id = wayland::make_wid(surface);
|
||||||
|
let window_handle = match winit_state.window_map.get(&window_id) {
|
||||||
|
Some(w) => w,
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
let scale_factor = sctk::get_surface_scale_factor(surface) as f64;
|
let scale_factor = window_handle.scale_factor();
|
||||||
let position = LogicalPosition::new(surface_x, surface_y).to_physical(scale_factor);
|
let position = LogicalPosition::new(surface_x, surface_y).to_physical(scale_factor);
|
||||||
|
|
||||||
event_sink.push_window_event(
|
event_sink.push_window_event(
|
||||||
|
@ -192,6 +196,10 @@ pub(super) fn handle_pointer(
|
||||||
};
|
};
|
||||||
|
|
||||||
let window_id = wayland::make_wid(surface);
|
let window_id = wayland::make_wid(surface);
|
||||||
|
let window_handle = match winit_state.window_map.get(&window_id) {
|
||||||
|
Some(w) => w,
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
if pointer.as_ref().version() < 5 {
|
if pointer.as_ref().version() < 5 {
|
||||||
let (mut x, mut y) = (0.0, 0.0);
|
let (mut x, mut y) = (0.0, 0.0);
|
||||||
|
@ -204,7 +212,7 @@ pub(super) fn handle_pointer(
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
let scale_factor = sctk::get_surface_scale_factor(surface) as f64;
|
let scale_factor = window_handle.scale_factor();
|
||||||
let delta = LogicalPosition::new(x as f64, y as f64).to_physical(scale_factor);
|
let delta = LogicalPosition::new(x as f64, y as f64).to_physical(scale_factor);
|
||||||
|
|
||||||
event_sink.push_window_event(
|
event_sink.push_window_event(
|
||||||
|
@ -268,6 +276,10 @@ pub(super) fn handle_pointer(
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
let window_id = wayland::make_wid(surface);
|
let window_id = wayland::make_wid(surface);
|
||||||
|
let window_handle = match winit_state.window_map.get(&window_id) {
|
||||||
|
Some(w) => w,
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
let window_event = if let Some((x, y)) = axis_discrete_buffer {
|
let window_event = if let Some((x, y)) = axis_discrete_buffer {
|
||||||
WindowEvent::MouseWheel {
|
WindowEvent::MouseWheel {
|
||||||
|
@ -279,7 +291,7 @@ pub(super) fn handle_pointer(
|
||||||
modifiers: *pointer_data.modifiers_state.borrow(),
|
modifiers: *pointer_data.modifiers_state.borrow(),
|
||||||
}
|
}
|
||||||
} else if let Some((x, y)) = axis_buffer {
|
} else if let Some((x, y)) = axis_buffer {
|
||||||
let scale_factor = sctk::get_surface_scale_factor(surface) as f64;
|
let scale_factor = window_handle.scale_factor();
|
||||||
let delta = LogicalPosition::new(x, y).to_physical(scale_factor);
|
let delta = LogicalPosition::new(x, y).to_physical(scale_factor);
|
||||||
|
|
||||||
WindowEvent::MouseWheel {
|
WindowEvent::MouseWheel {
|
||||||
|
|
|
@ -24,11 +24,12 @@ pub(super) fn handle_touch(
|
||||||
surface, id, x, y, ..
|
surface, id, x, y, ..
|
||||||
} => {
|
} => {
|
||||||
let window_id = wayland::make_wid(&surface);
|
let window_id = wayland::make_wid(&surface);
|
||||||
if !winit_state.window_map.contains_key(&window_id) {
|
let window_handle = match winit_state.window_map.get(&window_id) {
|
||||||
return;
|
Some(w) => w,
|
||||||
}
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
let scale_factor = sctk::get_surface_scale_factor(&surface) as f64;
|
let scale_factor = window_handle.scale_factor();
|
||||||
let position = LogicalPosition::new(x, y);
|
let position = LogicalPosition::new(x, y);
|
||||||
|
|
||||||
event_sink.push_window_event(
|
event_sink.push_window_event(
|
||||||
|
@ -60,7 +61,12 @@ pub(super) fn handle_touch(
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let scale_factor = sctk::get_surface_scale_factor(&touch_point.surface) as f64;
|
let window_id = wayland::make_wid(&touch_point.surface);
|
||||||
|
let window_handle = match winit_state.window_map.get(&window_id) {
|
||||||
|
Some(w) => w,
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
let scale_factor = window_handle.scale_factor();
|
||||||
let location = touch_point.position.to_physical(scale_factor);
|
let location = touch_point.position.to_physical(scale_factor);
|
||||||
let window_id = wayland::make_wid(&touch_point.surface);
|
let window_id = wayland::make_wid(&touch_point.surface);
|
||||||
|
|
||||||
|
@ -82,10 +88,15 @@ pub(super) fn handle_touch(
|
||||||
Some(touch_point) => touch_point,
|
Some(touch_point) => touch_point,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
let window_id = wayland::make_wid(&touch_point.surface);
|
||||||
|
let window_handle = match winit_state.window_map.get(&window_id) {
|
||||||
|
Some(w) => w,
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
touch_point.position = LogicalPosition::new(x, y);
|
touch_point.position = LogicalPosition::new(x, y);
|
||||||
|
|
||||||
let scale_factor = sctk::get_surface_scale_factor(&touch_point.surface) as f64;
|
let scale_factor = window_handle.scale_factor();
|
||||||
let location = touch_point.position.to_physical(scale_factor);
|
let location = touch_point.position.to_physical(scale_factor);
|
||||||
let window_id = wayland::make_wid(&touch_point.surface);
|
let window_id = wayland::make_wid(&touch_point.surface);
|
||||||
|
|
||||||
|
@ -105,9 +116,14 @@ pub(super) fn handle_touch(
|
||||||
TouchEvent::Frame => (),
|
TouchEvent::Frame => (),
|
||||||
TouchEvent::Cancel => {
|
TouchEvent::Cancel => {
|
||||||
for touch_point in inner.touch_points.drain(..) {
|
for touch_point in inner.touch_points.drain(..) {
|
||||||
let scale_factor = sctk::get_surface_scale_factor(&touch_point.surface) as f64;
|
|
||||||
let location = touch_point.position.to_physical(scale_factor);
|
|
||||||
let window_id = wayland::make_wid(&touch_point.surface);
|
let window_id = wayland::make_wid(&touch_point.surface);
|
||||||
|
let window_handle = match winit_state.window_map.get(&window_id) {
|
||||||
|
Some(w) => w,
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
let scale_factor = window_handle.scale_factor();
|
||||||
|
let location = touch_point.position.to_physical(scale_factor);
|
||||||
|
|
||||||
event_sink.push_window_event(
|
event_sink.push_window_event(
|
||||||
WindowEvent::Touch(crate::event::Touch {
|
WindowEvent::Touch(crate::event::Touch {
|
||||||
|
|
|
@ -11,12 +11,14 @@ use raw_window_handle::{
|
||||||
RawDisplayHandle, RawWindowHandle, WaylandDisplayHandle, WaylandWindowHandle,
|
RawDisplayHandle, RawWindowHandle, WaylandDisplayHandle, WaylandWindowHandle,
|
||||||
};
|
};
|
||||||
use sctk::window::Decorations;
|
use sctk::window::Decorations;
|
||||||
|
use wayland_protocols::viewporter::client::wp_viewporter::WpViewporter;
|
||||||
|
|
||||||
use crate::dpi::{LogicalSize, PhysicalPosition, PhysicalSize, Position, Size};
|
use crate::dpi::{LogicalSize, PhysicalPosition, PhysicalSize, Position, Size};
|
||||||
use crate::error::{ExternalError, NotSupportedError, OsError as RootOsError};
|
use crate::error::{ExternalError, NotSupportedError, OsError as RootOsError};
|
||||||
use crate::platform_impl::{
|
use crate::platform_impl::{
|
||||||
Fullscreen, MonitorHandle as PlatformMonitorHandle, OsError,
|
wayland::protocols::wp_fractional_scale_manager_v1::WpFractionalScaleManagerV1,
|
||||||
PlatformSpecificWindowBuilderAttributes as PlatformAttributes,
|
wayland::protocols::wp_fractional_scale_v1, Fullscreen, MonitorHandle as PlatformMonitorHandle,
|
||||||
|
OsError, PlatformSpecificWindowBuilderAttributes as PlatformAttributes,
|
||||||
};
|
};
|
||||||
use crate::window::{
|
use crate::window::{
|
||||||
CursorGrabMode, CursorIcon, ResizeDirection, Theme, UserAttentionType, WindowAttributes,
|
CursorGrabMode, CursorIcon, ResizeDirection, Theme, UserAttentionType, WindowAttributes,
|
||||||
|
@ -30,7 +32,9 @@ use super::{EventLoopWindowTarget, WindowId};
|
||||||
|
|
||||||
pub mod shim;
|
pub mod shim;
|
||||||
|
|
||||||
use shim::{WindowCompositorUpdate, WindowHandle, WindowRequest, WindowUserRequest};
|
use shim::{
|
||||||
|
FractionalScalingState, WindowCompositorUpdate, WindowHandle, WindowRequest, WindowUserRequest,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(feature = "sctk-adwaita")]
|
#[cfg(feature = "sctk-adwaita")]
|
||||||
pub type WinitFrame = sctk_adwaita::AdwaitaFrame;
|
pub type WinitFrame = sctk_adwaita::AdwaitaFrame;
|
||||||
|
@ -50,6 +54,9 @@ pub struct Window {
|
||||||
/// The underlying wl_surface.
|
/// The underlying wl_surface.
|
||||||
surface: WlSurface,
|
surface: WlSurface,
|
||||||
|
|
||||||
|
/// The scale factor.
|
||||||
|
scale_factor: Arc<Mutex<f64>>,
|
||||||
|
|
||||||
/// The current window size.
|
/// The current window size.
|
||||||
size: Arc<Mutex<LogicalSize<u32>>>,
|
size: Arc<Mutex<LogicalSize<u32>>>,
|
||||||
|
|
||||||
|
@ -90,33 +97,50 @@ impl Window {
|
||||||
attributes: WindowAttributes,
|
attributes: WindowAttributes,
|
||||||
platform_attributes: PlatformAttributes,
|
platform_attributes: PlatformAttributes,
|
||||||
) -> Result<Self, RootOsError> {
|
) -> Result<Self, RootOsError> {
|
||||||
let surface = event_loop_window_target
|
let viewporter = event_loop_window_target.env.get_global::<WpViewporter>();
|
||||||
|
let fractional_scale_manager = event_loop_window_target
|
||||||
.env
|
.env
|
||||||
.create_surface_with_scale_callback(move |scale, surface, mut dispatch_data| {
|
.get_global::<WpFractionalScaleManagerV1>();
|
||||||
let winit_state = dispatch_data.get::<WinitState>().unwrap();
|
|
||||||
|
// Create surface and register callback for the scale factor changes.
|
||||||
|
let mut scale_factor = 1.;
|
||||||
|
let (surface, fractional_scaling_state) =
|
||||||
|
if let (Some(viewporter), Some(fractional_scale_manager)) =
|
||||||
|
(viewporter, fractional_scale_manager)
|
||||||
|
{
|
||||||
|
let surface = event_loop_window_target.env.create_surface().detach();
|
||||||
|
let fractional_scale = fractional_scale_manager.get_fractional_scale(&surface);
|
||||||
|
|
||||||
// Get the window that received the event.
|
|
||||||
let window_id = super::make_wid(&surface);
|
let window_id = super::make_wid(&surface);
|
||||||
let mut window_compositor_update = winit_state
|
fractional_scale.quick_assign(move |_, event, mut dispatch_data| {
|
||||||
.window_compositor_updates
|
let wp_fractional_scale_v1::Event::PreferredScale { scale } = event;
|
||||||
.get_mut(&window_id)
|
let winit_state = dispatch_data.get::<WinitState>().unwrap();
|
||||||
.unwrap();
|
apply_scale(window_id, scale as f64 / 120., winit_state);
|
||||||
|
});
|
||||||
|
|
||||||
// Mark that we need a frame refresh on the DPI change.
|
let fractional_scale = fractional_scale.detach();
|
||||||
winit_state
|
let viewport = viewporter.get_viewport(&surface).detach();
|
||||||
.window_user_requests
|
let fractional_scaling_state =
|
||||||
.get_mut(&window_id)
|
FractionalScalingState::new(viewport, fractional_scale);
|
||||||
.unwrap()
|
|
||||||
.refresh_frame = true;
|
|
||||||
|
|
||||||
// Set pending scale factor.
|
(surface, Some(fractional_scaling_state))
|
||||||
window_compositor_update.scale_factor = Some(scale);
|
} else {
|
||||||
|
let surface = event_loop_window_target
|
||||||
|
.env
|
||||||
|
.create_surface_with_scale_callback(move |scale, surface, mut dispatch_data| {
|
||||||
|
let winit_state = dispatch_data.get::<WinitState>().unwrap();
|
||||||
|
|
||||||
surface.set_buffer_scale(scale);
|
// Get the window that received the event.
|
||||||
})
|
let window_id = super::make_wid(&surface);
|
||||||
.detach();
|
apply_scale(window_id, scale as f64, winit_state);
|
||||||
|
surface.set_buffer_scale(scale);
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
|
||||||
let scale_factor = sctk::get_surface_scale_factor(&surface);
|
scale_factor = sctk::get_surface_scale_factor(&surface) as _;
|
||||||
|
|
||||||
|
(surface, None)
|
||||||
|
};
|
||||||
|
|
||||||
let window_id = super::make_wid(&surface);
|
let window_id = super::make_wid(&surface);
|
||||||
let maximized = Arc::new(AtomicBool::new(false));
|
let maximized = Arc::new(AtomicBool::new(false));
|
||||||
|
@ -126,7 +150,7 @@ impl Window {
|
||||||
|
|
||||||
let (width, height) = attributes
|
let (width, height) = attributes
|
||||||
.inner_size
|
.inner_size
|
||||||
.map(|size| size.to_logical::<f64>(scale_factor as f64).into())
|
.map(|size| size.to_logical::<f64>(scale_factor).into())
|
||||||
.unwrap_or((800, 600));
|
.unwrap_or((800, 600));
|
||||||
|
|
||||||
let theme_manager = event_loop_window_target.theme_manager.clone();
|
let theme_manager = event_loop_window_target.theme_manager.clone();
|
||||||
|
@ -194,13 +218,13 @@ impl Window {
|
||||||
// Min dimensions.
|
// Min dimensions.
|
||||||
let min_size = attributes
|
let min_size = attributes
|
||||||
.min_inner_size
|
.min_inner_size
|
||||||
.map(|size| size.to_logical::<f64>(scale_factor as f64).into());
|
.map(|size| size.to_logical::<f64>(scale_factor).into());
|
||||||
window.set_min_size(min_size);
|
window.set_min_size(min_size);
|
||||||
|
|
||||||
// Max dimensions.
|
// Max dimensions.
|
||||||
let max_size = attributes
|
let max_size = attributes
|
||||||
.max_inner_size
|
.max_inner_size
|
||||||
.map(|size| size.to_logical::<f64>(scale_factor as f64).into());
|
.map(|size| size.to_logical::<f64>(scale_factor).into());
|
||||||
window.set_max_size(max_size);
|
window.set_max_size(max_size);
|
||||||
|
|
||||||
// Set Wayland specific window attributes.
|
// Set Wayland specific window attributes.
|
||||||
|
@ -263,6 +287,8 @@ impl Window {
|
||||||
window,
|
window,
|
||||||
size.clone(),
|
size.clone(),
|
||||||
has_focus.clone(),
|
has_focus.clone(),
|
||||||
|
fractional_scaling_state,
|
||||||
|
scale_factor,
|
||||||
window_requests.clone(),
|
window_requests.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -324,6 +350,7 @@ impl Window {
|
||||||
decorated: AtomicBool::new(attributes.decorations),
|
decorated: AtomicBool::new(attributes.decorations),
|
||||||
cursor_grab_mode: Mutex::new(CursorGrabMode::None),
|
cursor_grab_mode: Mutex::new(CursorGrabMode::None),
|
||||||
has_focus,
|
has_focus,
|
||||||
|
scale_factor: window_handle.scale_factor.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(window)
|
Ok(window)
|
||||||
|
@ -372,10 +399,7 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inner_size(&self) -> PhysicalSize<u32> {
|
pub fn inner_size(&self) -> PhysicalSize<u32> {
|
||||||
self.size
|
self.size.lock().unwrap().to_physical(self.scale_factor())
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.to_physical(self.scale_factor() as f64)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -385,15 +409,12 @@ impl Window {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn outer_size(&self) -> PhysicalSize<u32> {
|
pub fn outer_size(&self) -> PhysicalSize<u32> {
|
||||||
self.size
|
self.size.lock().unwrap().to_physical(self.scale_factor())
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.to_physical(self.scale_factor() as f64)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_inner_size(&self, size: Size) {
|
pub fn set_inner_size(&self, size: Size) {
|
||||||
let scale_factor = self.scale_factor() as f64;
|
let scale_factor = self.scale_factor();
|
||||||
|
|
||||||
let size = size.to_logical::<u32>(scale_factor);
|
let size = size.to_logical::<u32>(scale_factor);
|
||||||
*self.size.lock().unwrap() = size;
|
*self.size.lock().unwrap() = size;
|
||||||
|
@ -403,7 +424,7 @@ impl Window {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_min_inner_size(&self, dimensions: Option<Size>) {
|
pub fn set_min_inner_size(&self, dimensions: Option<Size>) {
|
||||||
let scale_factor = self.scale_factor() as f64;
|
let scale_factor = self.scale_factor();
|
||||||
let size = dimensions.map(|size| size.to_logical::<u32>(scale_factor));
|
let size = dimensions.map(|size| size.to_logical::<u32>(scale_factor));
|
||||||
|
|
||||||
self.send_request(WindowRequest::MinSize(size));
|
self.send_request(WindowRequest::MinSize(size));
|
||||||
|
@ -411,7 +432,7 @@ impl Window {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_max_inner_size(&self, dimensions: Option<Size>) {
|
pub fn set_max_inner_size(&self, dimensions: Option<Size>) {
|
||||||
let scale_factor = self.scale_factor() as f64;
|
let scale_factor = self.scale_factor();
|
||||||
let size = dimensions.map(|size| size.to_logical::<u32>(scale_factor));
|
let size = dimensions.map(|size| size.to_logical::<u32>(scale_factor));
|
||||||
|
|
||||||
self.send_request(WindowRequest::MaxSize(size));
|
self.send_request(WindowRequest::MaxSize(size));
|
||||||
|
@ -447,10 +468,8 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn scale_factor(&self) -> u32 {
|
pub fn scale_factor(&self) -> f64 {
|
||||||
// The scale factor from `get_surface_scale_factor` is always greater than zero, so
|
*self.scale_factor.lock().unwrap()
|
||||||
// u32 conversion is safe.
|
|
||||||
sctk::get_surface_scale_factor(&self.surface) as u32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -561,7 +580,7 @@ impl Window {
|
||||||
))));
|
))));
|
||||||
}
|
}
|
||||||
|
|
||||||
let scale_factor = self.scale_factor() as f64;
|
let scale_factor = self.scale_factor();
|
||||||
let position = position.to_logical(scale_factor);
|
let position = position.to_logical(scale_factor);
|
||||||
self.send_request(WindowRequest::SetLockedCursorPosition(position));
|
self.send_request(WindowRequest::SetLockedCursorPosition(position));
|
||||||
|
|
||||||
|
@ -589,7 +608,7 @@ impl Window {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_ime_position(&self, position: Position) {
|
pub fn set_ime_position(&self, position: Position) {
|
||||||
let scale_factor = self.scale_factor() as f64;
|
let scale_factor = self.scale_factor();
|
||||||
let position = position.to_logical(scale_factor);
|
let position = position.to_logical(scale_factor);
|
||||||
self.send_request(WindowRequest::ImePosition(position));
|
self.send_request(WindowRequest::ImePosition(position));
|
||||||
}
|
}
|
||||||
|
@ -700,3 +719,20 @@ impl TryFrom<&str> for Theme {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set pending scale for the provided `window_id`.
|
||||||
|
fn apply_scale(window_id: WindowId, scale: f64, winit_state: &mut WinitState) {
|
||||||
|
// Set pending scale factor.
|
||||||
|
winit_state
|
||||||
|
.window_compositor_updates
|
||||||
|
.get_mut(&window_id)
|
||||||
|
.unwrap()
|
||||||
|
.scale_factor = Some(scale);
|
||||||
|
|
||||||
|
// Mark that we need a frame refresh on the DPI change.
|
||||||
|
winit_state
|
||||||
|
.window_user_requests
|
||||||
|
.get_mut(&window_id)
|
||||||
|
.unwrap()
|
||||||
|
.refresh_frame = true;
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ use sctk::reexports::protocols::staging::xdg_activation::v1::client::xdg_activat
|
||||||
|
|
||||||
use sctk::environment::Environment;
|
use sctk::environment::Environment;
|
||||||
use sctk::window::{Decorations, Window};
|
use sctk::window::{Decorations, Window};
|
||||||
|
use wayland_protocols::viewporter::client::wp_viewport::WpViewport;
|
||||||
|
|
||||||
use crate::dpi::{LogicalPosition, LogicalSize};
|
use crate::dpi::{LogicalPosition, LogicalSize};
|
||||||
|
|
||||||
|
@ -18,6 +19,7 @@ use crate::event::{Ime, WindowEvent};
|
||||||
use crate::platform_impl::wayland;
|
use crate::platform_impl::wayland;
|
||||||
use crate::platform_impl::wayland::env::WinitEnv;
|
use crate::platform_impl::wayland::env::WinitEnv;
|
||||||
use crate::platform_impl::wayland::event_loop::{EventSink, WinitState};
|
use crate::platform_impl::wayland::event_loop::{EventSink, WinitState};
|
||||||
|
use crate::platform_impl::wayland::protocols::wp_fractional_scale_v1::WpFractionalScaleV1;
|
||||||
use crate::platform_impl::wayland::seat::pointer::WinitPointer;
|
use crate::platform_impl::wayland::seat::pointer::WinitPointer;
|
||||||
use crate::platform_impl::wayland::seat::text_input::TextInputHandler;
|
use crate::platform_impl::wayland::seat::text_input::TextInputHandler;
|
||||||
use crate::platform_impl::wayland::WindowId;
|
use crate::platform_impl::wayland::WindowId;
|
||||||
|
@ -109,7 +111,7 @@ pub struct WindowCompositorUpdate {
|
||||||
pub size: Option<LogicalSize<u32>>,
|
pub size: Option<LogicalSize<u32>>,
|
||||||
|
|
||||||
/// New scale factor.
|
/// New scale factor.
|
||||||
pub scale_factor: Option<i32>,
|
pub scale_factor: Option<f64>,
|
||||||
|
|
||||||
/// Close the window.
|
/// Close the window.
|
||||||
pub close_window: bool,
|
pub close_window: bool,
|
||||||
|
@ -143,6 +145,12 @@ pub struct WindowHandle {
|
||||||
/// An actual window.
|
/// An actual window.
|
||||||
pub window: ManuallyDrop<Window<WinitFrame>>,
|
pub window: ManuallyDrop<Window<WinitFrame>>,
|
||||||
|
|
||||||
|
/// The state of the fractional scaling handlers for the window.
|
||||||
|
pub fractional_scaling_state: Option<FractionalScalingState>,
|
||||||
|
|
||||||
|
/// The scale factor of the window.
|
||||||
|
pub scale_factor: Arc<Mutex<f64>>,
|
||||||
|
|
||||||
/// The current size of the window.
|
/// The current size of the window.
|
||||||
pub size: Arc<Mutex<LogicalSize<u32>>>,
|
pub size: Arc<Mutex<LogicalSize<u32>>>,
|
||||||
|
|
||||||
|
@ -192,6 +200,8 @@ impl WindowHandle {
|
||||||
window: Window<WinitFrame>,
|
window: Window<WinitFrame>,
|
||||||
size: Arc<Mutex<LogicalSize<u32>>>,
|
size: Arc<Mutex<LogicalSize<u32>>>,
|
||||||
has_focus: Arc<AtomicBool>,
|
has_focus: Arc<AtomicBool>,
|
||||||
|
fractional_scaling_state: Option<FractionalScalingState>,
|
||||||
|
scale_factor: f64,
|
||||||
pending_window_requests: Arc<Mutex<Vec<WindowRequest>>>,
|
pending_window_requests: Arc<Mutex<Vec<WindowRequest>>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let xdg_activation = env.get_global::<XdgActivationV1>();
|
let xdg_activation = env.get_global::<XdgActivationV1>();
|
||||||
|
@ -201,6 +211,8 @@ impl WindowHandle {
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
window: ManuallyDrop::new(window),
|
window: ManuallyDrop::new(window),
|
||||||
|
fractional_scaling_state,
|
||||||
|
scale_factor: Arc::new(Mutex::new(scale_factor)),
|
||||||
size,
|
size,
|
||||||
pending_window_requests,
|
pending_window_requests,
|
||||||
cursor_icon: Cell::new(CursorIcon::Default),
|
cursor_icon: Cell::new(CursorIcon::Default),
|
||||||
|
@ -218,6 +230,10 @@ impl WindowHandle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn scale_factor(&self) -> f64 {
|
||||||
|
*self.scale_factor.lock().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_cursor_grab(&self, mode: CursorGrabMode) {
|
pub fn set_cursor_grab(&self, mode: CursorGrabMode) {
|
||||||
// The new requested state matches the current confine status, return.
|
// The new requested state matches the current confine status, return.
|
||||||
let old_mode = self.cursor_grab_mode.replace(mode);
|
let old_mode = self.cursor_grab_mode.replace(mode);
|
||||||
|
@ -587,6 +603,9 @@ pub fn handle_window_requests(winit_state: &mut WinitState) {
|
||||||
|
|
||||||
impl Drop for WindowHandle {
|
impl Drop for WindowHandle {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
// Drop the fractional scaling before the surface.
|
||||||
|
let _ = self.fractional_scaling_state.take();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let surface = self.window.surface().clone();
|
let surface = self.window.surface().clone();
|
||||||
// The window must be destroyed before wl_surface.
|
// The window must be destroyed before wl_surface.
|
||||||
|
@ -595,3 +614,28 @@ impl Drop for WindowHandle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fractional scaling objects.
|
||||||
|
pub struct FractionalScalingState {
|
||||||
|
/// The wp-viewport of the window.
|
||||||
|
pub viewport: WpViewport,
|
||||||
|
|
||||||
|
/// The wp-fractional-scale of the window surface.
|
||||||
|
pub fractional_scale: WpFractionalScaleV1,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FractionalScalingState {
|
||||||
|
pub fn new(viewport: WpViewport, fractional_scale: WpFractionalScaleV1) -> Self {
|
||||||
|
Self {
|
||||||
|
viewport,
|
||||||
|
fractional_scale,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for FractionalScalingState {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.viewport.destroy();
|
||||||
|
self.fractional_scale.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -486,6 +486,7 @@ impl Window {
|
||||||
/// ## Platform-specific
|
/// ## Platform-specific
|
||||||
///
|
///
|
||||||
/// - **X11:** This respects Xft.dpi, and can be overridden using the `WINIT_X11_SCALE_FACTOR` environment variable.
|
/// - **X11:** This respects Xft.dpi, and can be overridden using the `WINIT_X11_SCALE_FACTOR` environment variable.
|
||||||
|
/// - **Wayland:** Uses the wp-fractional-scale protocol if available. Falls back to integer-scale factors otherwise.
|
||||||
/// - **Android:** Always returns 1.0.
|
/// - **Android:** Always returns 1.0.
|
||||||
/// - **iOS:** Can only be called on the main thread. Returns the underlying `UIView`'s
|
/// - **iOS:** Can only be called on the main thread. Returns the underlying `UIView`'s
|
||||||
/// [`contentScaleFactor`].
|
/// [`contentScaleFactor`].
|
||||||
|
|
102
wayland_protocols/fractional-scale-v1.xml
Normal file
102
wayland_protocols/fractional-scale-v1.xml
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<protocol name="fractional_scale_v1">
|
||||||
|
<copyright>
|
||||||
|
Copyright © 2022 Kenny Levinsen
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice (including the next
|
||||||
|
paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
</copyright>
|
||||||
|
|
||||||
|
<description summary="Protocol for requesting fractional surface scales">
|
||||||
|
This protocol allows a compositor to suggest for surfaces to render at
|
||||||
|
fractional scales.
|
||||||
|
|
||||||
|
A client can submit scaled content by utilizing wp_viewport. This is done by
|
||||||
|
creating a wp_viewport object for the surface and setting the destination
|
||||||
|
rectangle to the surface size before the scale factor is applied.
|
||||||
|
|
||||||
|
The buffer size is calculated by multiplying the surface size by the
|
||||||
|
intended scale.
|
||||||
|
|
||||||
|
The wl_surface buffer scale should remain set to 1.
|
||||||
|
|
||||||
|
If a surface has a surface-local size of 100 px by 50 px and wishes to
|
||||||
|
submit buffers with a scale of 1.5, then a buffer of 150px by 75 px should
|
||||||
|
be used and the wp_viewport destination rectangle should be 100 px by 50 px.
|
||||||
|
|
||||||
|
For toplevel surfaces, the size is rounded halfway away from zero. The
|
||||||
|
rounding algorithm for subsurface position and size is not defined.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<interface name="wp_fractional_scale_manager_v1" version="1">
|
||||||
|
<description summary="fractional surface scale information">
|
||||||
|
A global interface for requesting surfaces to use fractional scales.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="unbind the fractional surface scale interface">
|
||||||
|
Informs the server that the client will not be using this protocol
|
||||||
|
object anymore. This does not affect any other objects,
|
||||||
|
wp_fractional_scale_v1 objects included.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<enum name="error">
|
||||||
|
<entry name="fractional_scale_exists" value="0"
|
||||||
|
summary="the surface already has a fractional_scale object associated"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<request name="get_fractional_scale">
|
||||||
|
<description summary="extend surface interface for scale information">
|
||||||
|
Create an add-on object for the the wl_surface to let the compositor
|
||||||
|
request fractional scales. If the given wl_surface already has a
|
||||||
|
wp_fractional_scale_v1 object associated, the fractional_scale_exists
|
||||||
|
protocol error is raised.
|
||||||
|
</description>
|
||||||
|
<arg name="id" type="new_id" interface="wp_fractional_scale_v1"
|
||||||
|
summary="the new surface scale info interface id"/>
|
||||||
|
<arg name="surface" type="object" interface="wl_surface"
|
||||||
|
summary="the surface"/>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="wp_fractional_scale_v1" version="1">
|
||||||
|
<description summary="fractional scale interface to a wl_surface">
|
||||||
|
An additional interface to a wl_surface object which allows the compositor
|
||||||
|
to inform the client of the preferred scale.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="remove surface scale information for surface">
|
||||||
|
Destroy the fractional scale object. When this object is destroyed,
|
||||||
|
preferred_scale events will no longer be sent.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<event name="preferred_scale">
|
||||||
|
<description summary="notify of new preferred scale">
|
||||||
|
Notification of a new preferred scale for this surface that the
|
||||||
|
compositor suggests that the client should use.
|
||||||
|
|
||||||
|
The sent scale is the numerator of a fraction with a denominator of 120.
|
||||||
|
</description>
|
||||||
|
<arg name="scale" type="uint" summary="the new preferred scale"/>
|
||||||
|
</event>
|
||||||
|
</interface>
|
||||||
|
</protocol>
|
Loading…
Reference in a new issue