wayland: implement scaling
This involves many subsystems:
- config:
- allow setting the connector scale
- allow setting the cursor size
- cursors:
- load server cursors for all requested sizes and scales
- wl_surface:
- track the output the surface belongs to
- send wl_surface.enter/leave
- wl_output:
- implement wl_output.scale
- text:
- pre-render texts for all used scales
- renderer:
- properly align scale textures and rectangles
- wp_fractional_scale:
- new interface for fractional scaling
This commit is contained in:
parent
16aec8f87e
commit
e52a60b3b6
41 changed files with 1417 additions and 364 deletions
|
|
@ -5,8 +5,8 @@ use {
|
|||
format::XRGB8888,
|
||||
globals::{Global, GlobalName},
|
||||
ifs::{
|
||||
wl_buffer::WlBufferStorage, zwlr_screencopy_frame_v1::ZwlrScreencopyFrameV1,
|
||||
zxdg_output_v1::ZxdgOutputV1,
|
||||
wl_buffer::WlBufferStorage, wl_surface::WlSurface,
|
||||
zwlr_screencopy_frame_v1::ZwlrScreencopyFrameV1, zxdg_output_v1::ZxdgOutputV1,
|
||||
},
|
||||
leaks::Tracker,
|
||||
object::Object,
|
||||
|
|
@ -72,6 +72,7 @@ pub struct WlOutputGlobal {
|
|||
pub unused_captures: LinkedList<Rc<ZwlrScreencopyFrameV1>>,
|
||||
pub pending_captures: LinkedList<Rc<ZwlrScreencopyFrameV1>>,
|
||||
pub destroyed: Cell<bool>,
|
||||
pub legacy_scale: Cell<i32>,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq)]
|
||||
|
|
@ -117,6 +118,7 @@ impl WlOutputGlobal {
|
|||
unused_captures: Default::default(),
|
||||
pending_captures: Default::default(),
|
||||
destroyed: Cell::new(false),
|
||||
legacy_scale: Cell::new(1),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -124,6 +126,27 @@ impl WlOutputGlobal {
|
|||
self.pos.get()
|
||||
}
|
||||
|
||||
pub fn for_each_binding<F: FnMut(&Rc<WlOutput>)>(&self, client: ClientId, mut f: F) {
|
||||
let bindings = self.bindings.borrow_mut();
|
||||
if let Some(bindings) = bindings.get(&client) {
|
||||
for binding in bindings.values() {
|
||||
f(binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_enter(&self, surface: &WlSurface) {
|
||||
self.for_each_binding(surface.client.id, |b| {
|
||||
surface.send_enter(b.id);
|
||||
})
|
||||
}
|
||||
|
||||
pub fn send_leave(&self, surface: &WlSurface) {
|
||||
self.for_each_binding(surface.client.id, |b| {
|
||||
surface.send_leave(b.id);
|
||||
})
|
||||
}
|
||||
|
||||
pub fn send_mode(&self) {
|
||||
let bindings = self.bindings.borrow_mut();
|
||||
for binding in bindings.values() {
|
||||
|
|
@ -293,7 +316,7 @@ impl WlOutput {
|
|||
fn send_scale(self: &Rc<Self>) {
|
||||
let event = Scale {
|
||||
self_id: self.id,
|
||||
factor: 1,
|
||||
factor: self.global.legacy_scale.get(),
|
||||
};
|
||||
self.client.event(event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,11 +149,20 @@ pub struct WlSeatGlobal {
|
|||
output: CloneCell<Rc<OutputNode>>,
|
||||
desired_known_cursor: Cell<Option<KnownCursor>>,
|
||||
changes: NumCell<u32>,
|
||||
cursor_size: Cell<u32>,
|
||||
}
|
||||
|
||||
const CHANGE_CURSOR_MOVED: u32 = 1 << 0;
|
||||
const CHANGE_TREE: u32 = 1 << 1;
|
||||
|
||||
const DEFAULT_CURSOR_SIZE: u32 = 16;
|
||||
|
||||
impl Drop for WlSeatGlobal {
|
||||
fn drop(&mut self) {
|
||||
self.state.remove_cursor_size(self.cursor_size.get());
|
||||
}
|
||||
}
|
||||
|
||||
impl WlSeatGlobal {
|
||||
pub fn new(name: GlobalName, seat_name: &str, state: &Rc<State>) -> Rc<Self> {
|
||||
let slf = Rc::new(Self {
|
||||
|
|
@ -192,7 +201,9 @@ impl WlSeatGlobal {
|
|||
output: CloneCell::new(state.dummy_output.get().unwrap()),
|
||||
desired_known_cursor: Cell::new(None),
|
||||
changes: NumCell::new(CHANGE_CURSOR_MOVED | CHANGE_TREE),
|
||||
cursor_size: Cell::new(DEFAULT_CURSOR_SIZE),
|
||||
});
|
||||
state.add_cursor_size(DEFAULT_CURSOR_SIZE);
|
||||
let seat = slf.clone();
|
||||
let future = state.eng.spawn(async move {
|
||||
loop {
|
||||
|
|
@ -207,6 +218,15 @@ impl WlSeatGlobal {
|
|||
slf
|
||||
}
|
||||
|
||||
pub fn set_cursor_size(&self, size: u32) {
|
||||
let old = self.cursor_size.replace(size);
|
||||
if size != old {
|
||||
self.state.remove_cursor_size(old);
|
||||
self.state.add_cursor_size(size);
|
||||
self.reload_known_cursor();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_data_device(&self, device: &Rc<WlDataDevice>) {
|
||||
let mut dd = self.data_devices.borrow_mut();
|
||||
dd.entry(device.client.id)
|
||||
|
|
@ -342,15 +362,25 @@ impl WlSeatGlobal {
|
|||
pub fn set_position(&self, x: i32, y: i32) {
|
||||
self.pos.set((Fixed::from_int(x), Fixed::from_int(y)));
|
||||
self.trigger_tree_changed();
|
||||
'set_output: {
|
||||
let output = 'set_output: {
|
||||
let outputs = self.state.outputs.lock();
|
||||
for output in outputs.values() {
|
||||
if output.node.global.pos.get().contains(x, y) {
|
||||
self.output.set(output.node.clone());
|
||||
break 'set_output;
|
||||
break 'set_output output.node.clone();
|
||||
}
|
||||
}
|
||||
self.output.set(self.state.dummy_output.get().unwrap());
|
||||
self.state.dummy_output.get().unwrap()
|
||||
};
|
||||
self.set_output(&output);
|
||||
}
|
||||
|
||||
fn set_output(&self, output: &Rc<OutputNode>) {
|
||||
self.output.set(output.clone());
|
||||
if let Some(cursor) = self.cursor.get() {
|
||||
cursor.set_output(output);
|
||||
}
|
||||
if let Some(dnd) = self.pointer_owner.dnd_icon() {
|
||||
dnd.set_output(output);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -547,6 +577,9 @@ impl WlSeatGlobal {
|
|||
icon: Option<Rc<WlSurface>>,
|
||||
serial: u32,
|
||||
) -> Result<(), WlSeatError> {
|
||||
if let Some(icon) = &icon {
|
||||
icon.set_output(&self.output.get());
|
||||
}
|
||||
self.pointer_owner
|
||||
.start_drag(self, origin, source, icon, serial)
|
||||
}
|
||||
|
|
@ -604,6 +637,12 @@ impl WlSeatGlobal {
|
|||
self.set_selection_::<PrimarySelectionIpc>(&self.primary_selection, selection)
|
||||
}
|
||||
|
||||
pub fn reload_known_cursor(&self) {
|
||||
if let Some(kc) = self.desired_known_cursor.get() {
|
||||
self.set_known_cursor(kc);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_known_cursor(&self, cursor: KnownCursor) {
|
||||
self.desired_known_cursor.set(Some(cursor));
|
||||
let cursors = match self.state.cursors.get() {
|
||||
|
|
@ -622,7 +661,7 @@ impl WlSeatGlobal {
|
|||
KnownCursor::ResizeBottomLeft => &cursors.resize_bottom_left,
|
||||
KnownCursor::ResizeBottomRight => &cursors.resize_bottom_right,
|
||||
};
|
||||
self.set_cursor2(Some(tpl.instantiate()));
|
||||
self.set_cursor2(Some(tpl.instantiate(self.cursor_size.get())));
|
||||
}
|
||||
|
||||
pub fn set_app_cursor(&self, cursor: Option<Rc<dyn Cursor>>) {
|
||||
|
|
@ -640,8 +679,7 @@ impl WlSeatGlobal {
|
|||
old.handle_unset();
|
||||
}
|
||||
if let Some(cursor) = cursor.as_ref() {
|
||||
let (x, y) = self.pos.get();
|
||||
cursor.set_position(x.round_down(), y.round_down());
|
||||
cursor.set_output(&self.output.get());
|
||||
}
|
||||
self.cursor.set(cursor);
|
||||
}
|
||||
|
|
@ -654,6 +692,10 @@ impl WlSeatGlobal {
|
|||
self.pointer_owner.remove_dnd_icon();
|
||||
}
|
||||
|
||||
pub fn get_position(&self) -> (Fixed, Fixed) {
|
||||
self.pos.get()
|
||||
}
|
||||
|
||||
pub fn get_cursor(&self) -> Option<Rc<dyn Cursor>> {
|
||||
self.cursor.get()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ impl WlSeatGlobal {
|
|||
Some(o) => o,
|
||||
_ => return,
|
||||
};
|
||||
self.output.set(output.node.clone());
|
||||
self.set_output(&output.node);
|
||||
let pos = output.node.global.pos.get();
|
||||
x += Fixed::from_int(pos.x1());
|
||||
y += Fixed::from_int(pos.y1());
|
||||
|
|
@ -247,7 +247,7 @@ impl WlSeatGlobal {
|
|||
let outputs = self.state.outputs.lock();
|
||||
for output in outputs.values() {
|
||||
if output.node.global.pos.get().contains(x_int, y_int) {
|
||||
self.output.set(output.node.clone());
|
||||
self.set_output(&output.node);
|
||||
break 'warp;
|
||||
}
|
||||
}
|
||||
|
|
@ -261,8 +261,8 @@ impl WlSeatGlobal {
|
|||
} else if y_int >= pos.y2() {
|
||||
y_int = pos.y2() - 1;
|
||||
}
|
||||
x = x.apply_fract(x_int);
|
||||
y = y.apply_fract(y_int);
|
||||
x = Fixed::from_int(x_int);
|
||||
y = Fixed::from_int(y_int);
|
||||
}
|
||||
}
|
||||
self.set_new_position(time_usec, x, y);
|
||||
|
|
@ -480,9 +480,6 @@ impl WlSeatGlobal {
|
|||
fn set_new_position(self: &Rc<Self>, time_usec: u64, x: Fixed, y: Fixed) {
|
||||
self.pos_time_usec.set(time_usec);
|
||||
self.pos.set((x, y));
|
||||
if let Some(cursor) = self.cursor.get() {
|
||||
cursor.set_position(x.round_down(), y.round_down());
|
||||
}
|
||||
self.changes.or_assign(CHANGE_CURSOR_MOVED);
|
||||
self.apply_changes();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
pub mod cursor;
|
||||
pub mod ext_session_lock_surface_v1;
|
||||
pub mod wl_subsurface;
|
||||
pub mod wp_fractional_scale_v1;
|
||||
pub mod wp_viewport;
|
||||
pub mod xdg_surface;
|
||||
pub mod xwindow;
|
||||
|
|
@ -21,7 +22,8 @@ use {
|
|||
},
|
||||
wl_seat::{wl_pointer::PendingScroll, Dnd, NodeSeatState, SeatId, WlSeatGlobal},
|
||||
wl_surface::{
|
||||
cursor::CursorSurface, wl_subsurface::WlSubsurface, wp_viewport::WpViewport,
|
||||
cursor::CursorSurface, wl_subsurface::WlSubsurface,
|
||||
wp_fractional_scale_v1::WpFractionalScaleV1, wp_viewport::WpViewport,
|
||||
xdg_surface::XdgSurfaceError, zwlr_layer_surface_v1::ZwlrLayerSurfaceV1Error,
|
||||
},
|
||||
wp_presentation_feedback::WpPresentationFeedback,
|
||||
|
|
@ -31,7 +33,10 @@ use {
|
|||
rect::{Rect, Region},
|
||||
render::Renderer,
|
||||
state::DeviceHandlerData,
|
||||
tree::{FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, ToplevelNode},
|
||||
tree::{
|
||||
FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, NodeVisitorBase, OutputNode,
|
||||
ToplevelNode,
|
||||
},
|
||||
utils::{
|
||||
buffd::{MsgParser, MsgParserError},
|
||||
clonecell::CloneCell,
|
||||
|
|
@ -207,6 +212,14 @@ impl SurfaceRole {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct SurfaceSendPreferredScaleVisitor(pub Fixed);
|
||||
impl NodeVisitorBase for SurfaceSendPreferredScaleVisitor {
|
||||
fn visit_surface(&mut self, node: &Rc<WlSurface>) {
|
||||
node.send_preferred_scale();
|
||||
node.node_visit_children(self);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WlSurface {
|
||||
pub id: WlSurfaceId,
|
||||
pub node_id: SurfaceNodeId,
|
||||
|
|
@ -239,6 +252,8 @@ pub struct WlSurface {
|
|||
pub tracker: Tracker<Self>,
|
||||
idle_inhibitors: CopyHashMap<ZwpIdleInhibitorV1Id, Rc<ZwpIdleInhibitorV1>>,
|
||||
viewporter: CloneCell<Option<Rc<WpViewport>>>,
|
||||
output: CloneCell<Rc<OutputNode>>,
|
||||
fractional_scale: CloneCell<Option<Rc<WpFractionalScaleV1>>>,
|
||||
}
|
||||
|
||||
impl Debug for WlSurface {
|
||||
|
|
@ -370,6 +385,34 @@ impl WlSurface {
|
|||
tracker: Default::default(),
|
||||
idle_inhibitors: Default::default(),
|
||||
viewporter: Default::default(),
|
||||
output: CloneCell::new(client.state.dummy_output.get().unwrap()),
|
||||
fractional_scale: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_output(&self, output: &Rc<OutputNode>) {
|
||||
let old = self.output.set(output.clone());
|
||||
if old.id == output.id {
|
||||
return;
|
||||
}
|
||||
output.global.send_enter(self);
|
||||
old.global.send_leave(self);
|
||||
if old.preferred_scale.get() != output.preferred_scale.get() {
|
||||
if let Some(fs) = self.fractional_scale.get() {
|
||||
fs.send_preferred_scale();
|
||||
}
|
||||
}
|
||||
let children = self.children.borrow_mut();
|
||||
if let Some(children) = &*children {
|
||||
for ss in children.subsurfaces.values() {
|
||||
ss.surface.set_output(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_preferred_scale(&self) {
|
||||
if let Some(fs) = self.fractional_scale.get() {
|
||||
fs.send_preferred_scale();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -423,13 +466,20 @@ impl WlSurface {
|
|||
}
|
||||
}
|
||||
|
||||
fn send_enter(&self, output: WlOutputId) {
|
||||
pub fn send_enter(&self, output: WlOutputId) {
|
||||
self.client.event(Enter {
|
||||
self_id: self.id,
|
||||
output,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn send_leave(&self, output: WlOutputId) {
|
||||
self.client.event(Leave {
|
||||
self_id: self.id,
|
||||
output,
|
||||
})
|
||||
}
|
||||
|
||||
fn set_toplevel(&self, tl: Option<Rc<dyn ToplevelNode>>) {
|
||||
let ch = self.children.borrow();
|
||||
if let Some(ch) = &*ch {
|
||||
|
|
@ -967,6 +1017,7 @@ impl Object for WlSurface {
|
|||
self.pending.presentation_feedback.borrow_mut().clear();
|
||||
self.presentation_feedback.borrow_mut().clear();
|
||||
self.viewporter.take();
|
||||
self.fractional_scale.take();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
use {
|
||||
crate::{
|
||||
cursor::Cursor,
|
||||
fixed::Fixed,
|
||||
ifs::{wl_seat::WlSeatGlobal, wl_surface::WlSurface},
|
||||
leaks::Tracker,
|
||||
rect::Rect,
|
||||
render::Renderer,
|
||||
tree::OutputNode,
|
||||
},
|
||||
std::{cell::Cell, rc::Rc},
|
||||
};
|
||||
|
|
@ -13,7 +15,6 @@ pub struct CursorSurface {
|
|||
seat: Rc<WlSeatGlobal>,
|
||||
surface: Rc<WlSurface>,
|
||||
hotspot: Cell<(i32, i32)>,
|
||||
pos: Cell<(i32, i32)>,
|
||||
extents: Cell<Rect>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
|
@ -24,25 +25,16 @@ impl CursorSurface {
|
|||
seat: seat.clone(),
|
||||
surface: surface.clone(),
|
||||
hotspot: Cell::new((0, 0)),
|
||||
pos: Cell::new((0, 0)),
|
||||
extents: Cell::new(Default::default()),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn update_extents(&self) {
|
||||
let (pos_x, pos_y) = self.pos.get();
|
||||
let extents = self.extents.get();
|
||||
let (hot_x, hot_y) = self.hotspot.get();
|
||||
self.extents.set(
|
||||
Rect::new_sized(
|
||||
pos_x - hot_x,
|
||||
pos_y - hot_y,
|
||||
extents.width(),
|
||||
extents.height(),
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
self.extents
|
||||
.set(Rect::new_sized(-hot_x, -hot_y, extents.width(), extents.height()).unwrap());
|
||||
}
|
||||
|
||||
pub fn handle_surface_destroy(&self) {
|
||||
|
|
@ -69,21 +61,25 @@ impl CursorSurface {
|
|||
}
|
||||
|
||||
impl Cursor for CursorSurface {
|
||||
fn set_position(&self, x: i32, y: i32) {
|
||||
self.pos.set((x, y));
|
||||
self.update_extents();
|
||||
fn render(&self, renderer: &mut Renderer, x: Fixed, y: Fixed) {
|
||||
let extents = self.extents.get().move_(x.round_down(), y.round_down());
|
||||
if extents.intersects(&renderer.logical_extents()) {
|
||||
let scale = renderer.scale();
|
||||
if scale != 1 {
|
||||
let scale = scale.to_f64();
|
||||
let (hot_x, hot_y) = self.hotspot.get();
|
||||
let (hot_x, hot_y) = (Fixed::from_int(hot_x), Fixed::from_int(hot_y));
|
||||
let x = ((x - hot_x).to_f64() * scale).round() as _;
|
||||
let y = ((y - hot_y).to_f64() * scale).round() as _;
|
||||
renderer.render_surface_scaled(&self.surface, x, y, None);
|
||||
} else {
|
||||
renderer.render_surface(&self.surface, extents.x1(), extents.y1());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&self, renderer: &mut Renderer, x: i32, y: i32) {
|
||||
renderer.render_surface(&self.surface, x, y);
|
||||
}
|
||||
|
||||
fn get_hotspot(&self) -> (i32, i32) {
|
||||
self.hotspot.get()
|
||||
}
|
||||
|
||||
fn extents(&self) -> Rect {
|
||||
self.extents.get()
|
||||
fn set_output(&self, output: &Rc<OutputNode>) {
|
||||
self.surface.set_output(output);
|
||||
}
|
||||
|
||||
fn handle_unset(&self) {
|
||||
|
|
|
|||
78
src/ifs/wl_surface/wp_fractional_scale_v1.rs
Normal file
78
src/ifs/wl_surface/wp_fractional_scale_v1.rs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
use {
|
||||
crate::{
|
||||
client::{Client, ClientError},
|
||||
ifs::wl_surface::WlSurface,
|
||||
leaks::Tracker,
|
||||
object::Object,
|
||||
utils::buffd::{MsgParser, MsgParserError},
|
||||
wire::{wp_fractional_scale_v1::*, WpFractionalScaleV1Id},
|
||||
},
|
||||
std::rc::Rc,
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
pub struct WpFractionalScaleV1 {
|
||||
pub id: WpFractionalScaleV1Id,
|
||||
pub client: Rc<Client>,
|
||||
pub surface: Rc<WlSurface>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl WpFractionalScaleV1 {
|
||||
pub fn new(id: WpFractionalScaleV1Id, surface: &Rc<WlSurface>) -> Self {
|
||||
Self {
|
||||
id,
|
||||
client: surface.client.clone(),
|
||||
surface: surface.clone(),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn install(self: &Rc<Self>) -> Result<(), WpFractionalScaleError> {
|
||||
if self.surface.fractional_scale.get().is_some() {
|
||||
return Err(WpFractionalScaleError::Exists);
|
||||
}
|
||||
self.surface.fractional_scale.set(Some(self.clone()));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn send_preferred_scale(&self) {
|
||||
self.client.event(PreferredScale {
|
||||
self_id: self.id,
|
||||
scale: self.surface.output.get().preferred_scale.get(),
|
||||
});
|
||||
}
|
||||
|
||||
fn destroy(&self, msg: MsgParser<'_, '_>) -> Result<(), WpFractionalScaleError> {
|
||||
let _req: Destroy = self.client.parse(self, msg)?;
|
||||
self.surface.fractional_scale.take();
|
||||
self.client.remove_obj(self)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
WpFractionalScaleV1;
|
||||
|
||||
DESTROY => destroy,
|
||||
}
|
||||
|
||||
impl Object for WpFractionalScaleV1 {
|
||||
fn num_requests(&self) -> u32 {
|
||||
DESTROY + 1
|
||||
}
|
||||
}
|
||||
|
||||
simple_add_obj!(WpFractionalScaleV1);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum WpFractionalScaleError {
|
||||
#[error("Parsing failed")]
|
||||
MsgParserError(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
#[error("The surface already has a fractional scale extension attached")]
|
||||
Exists,
|
||||
}
|
||||
efrom!(WpFractionalScaleError, MsgParserError);
|
||||
efrom!(WpFractionalScaleError, ClientError);
|
||||
|
|
@ -124,6 +124,7 @@ impl XdgSurface {
|
|||
|
||||
fn set_workspace(&self, ws: &Rc<WorkspaceNode>) {
|
||||
self.workspace.set(Some(ws.clone()));
|
||||
self.surface.set_output(&ws.output.get());
|
||||
let pu = self.popups.lock();
|
||||
for pu in pu.values() {
|
||||
pu.xdg.set_workspace(ws);
|
||||
|
|
|
|||
|
|
@ -456,8 +456,7 @@ impl ToplevelNode for XdgToplevel {
|
|||
Some(self.xdg.surface.clone())
|
||||
}
|
||||
|
||||
fn tl_set_workspace(self: Rc<Self>, ws: &Rc<WorkspaceNode>) {
|
||||
self.toplevel_data.workspace.set(Some(ws.clone()));
|
||||
fn tl_set_workspace_ext(self: Rc<Self>, ws: &Rc<WorkspaceNode>) {
|
||||
self.xdg.set_workspace(ws);
|
||||
}
|
||||
|
||||
|
|
@ -548,12 +547,7 @@ impl XdgSurfaceExt for XdgToplevel {
|
|||
self.extents_changed();
|
||||
if let Some(workspace) = self.xdg.workspace.get() {
|
||||
let output = workspace.output.get();
|
||||
let bindings = output.global.bindings.borrow_mut();
|
||||
if let Some(binding) = bindings.get(&self.xdg.surface.client.id) {
|
||||
for binding in binding.values() {
|
||||
self.xdg.surface.send_enter(binding.id);
|
||||
}
|
||||
}
|
||||
surface.set_output(&output);
|
||||
}
|
||||
// {
|
||||
// let seats = surface.client.state.globals.lock_seats();
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use {
|
|||
state::State,
|
||||
tree::{
|
||||
Direction, FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, StackedNode,
|
||||
ToplevelData, ToplevelNode,
|
||||
ToplevelData, ToplevelNode, WorkspaceNode,
|
||||
},
|
||||
utils::{clonecell::CloneCell, copyhashmap::CopyHashMap, linkedlist::LinkedNode},
|
||||
wire::WlSurfaceId,
|
||||
|
|
@ -401,6 +401,10 @@ impl ToplevelNode for Xwindow {
|
|||
Some(self.surface.clone())
|
||||
}
|
||||
|
||||
fn tl_set_workspace_ext(self: Rc<Self>, ws: &Rc<WorkspaceNode>) {
|
||||
self.surface.set_output(&ws.output.get());
|
||||
}
|
||||
|
||||
fn tl_change_extents(self: Rc<Self>, rect: &Rect) {
|
||||
// log::info!("xwin {} change_extents {:?}", self.data.window_id, rect);
|
||||
let old = self.data.info.extents.replace(*rect);
|
||||
|
|
|
|||
112
src/ifs/wp_fractional_scale_manager_v1.rs
Normal file
112
src/ifs/wp_fractional_scale_manager_v1.rs
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
use {
|
||||
crate::{
|
||||
client::{Client, ClientError},
|
||||
globals::{Global, GlobalName},
|
||||
ifs::wl_surface::wp_fractional_scale_v1::{WpFractionalScaleError, WpFractionalScaleV1},
|
||||
leaks::Tracker,
|
||||
object::Object,
|
||||
utils::buffd::{MsgParser, MsgParserError},
|
||||
wire::{wp_fractional_scale_manager_v1::*, WpFractionalScaleManagerV1Id},
|
||||
},
|
||||
std::rc::Rc,
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
pub struct WpFractionalScaleManagerV1Global {
|
||||
pub name: GlobalName,
|
||||
}
|
||||
|
||||
pub struct WpFractionalScaleManagerV1 {
|
||||
pub id: WpFractionalScaleManagerV1Id,
|
||||
pub client: Rc<Client>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
impl WpFractionalScaleManagerV1Global {
|
||||
pub fn new(name: GlobalName) -> Self {
|
||||
Self { name }
|
||||
}
|
||||
|
||||
fn bind_(
|
||||
self: Rc<Self>,
|
||||
id: WpFractionalScaleManagerV1Id,
|
||||
client: &Rc<Client>,
|
||||
_version: u32,
|
||||
) -> Result<(), WpFractionalScaleManagerError> {
|
||||
let obj = Rc::new(WpFractionalScaleManagerV1 {
|
||||
id,
|
||||
client: client.clone(),
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(client, obj);
|
||||
client.add_client_obj(&obj)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
global_base!(
|
||||
WpFractionalScaleManagerV1Global,
|
||||
WpFractionalScaleManagerV1,
|
||||
WpFractionalScaleManagerError
|
||||
);
|
||||
|
||||
impl Global for WpFractionalScaleManagerV1Global {
|
||||
fn singleton(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn version(&self) -> u32 {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
simple_add_global!(WpFractionalScaleManagerV1Global);
|
||||
|
||||
impl WpFractionalScaleManagerV1 {
|
||||
fn destroy(&self, msg: MsgParser<'_, '_>) -> Result<(), WpFractionalScaleManagerError> {
|
||||
let _req: Destroy = self.client.parse(self, msg)?;
|
||||
self.client.remove_obj(self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_fractional_scale(
|
||||
&self,
|
||||
msg: MsgParser<'_, '_>,
|
||||
) -> Result<(), WpFractionalScaleManagerError> {
|
||||
let req: GetFractionalScale = self.client.parse(self, msg)?;
|
||||
let surface = self.client.lookup(req.surface)?;
|
||||
let fs = Rc::new(WpFractionalScaleV1::new(req.id, &surface));
|
||||
track!(self.client, fs);
|
||||
fs.install()?;
|
||||
self.client.add_client_obj(&fs)?;
|
||||
fs.send_preferred_scale();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
WpFractionalScaleManagerV1;
|
||||
|
||||
DESTROY => destroy,
|
||||
GET_FRACTIONAL_SCALE => get_fractional_scale,
|
||||
}
|
||||
|
||||
impl Object for WpFractionalScaleManagerV1 {
|
||||
fn num_requests(&self) -> u32 {
|
||||
GET_FRACTIONAL_SCALE + 1
|
||||
}
|
||||
}
|
||||
|
||||
simple_add_obj!(WpFractionalScaleManagerV1);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum WpFractionalScaleManagerError {
|
||||
#[error("Parsing failed")]
|
||||
MsgParserError(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
#[error(transparent)]
|
||||
WpFractionalScaleError(#[from] WpFractionalScaleError),
|
||||
}
|
||||
efrom!(WpFractionalScaleManagerError, MsgParserError);
|
||||
efrom!(WpFractionalScaleManagerError, ClientError);
|
||||
Loading…
Add table
Add a link
Reference in a new issue