1
0
Fork 0
forked from wry/wry

autocommit 2022-02-01 23:33:59 CET

This commit is contained in:
Julian Orth 2022-02-01 23:33:59 +01:00
parent 41c5f8cf89
commit 2dbe3ba732
21 changed files with 814 additions and 86 deletions

View file

@ -350,6 +350,9 @@ impl WlSeatGlobal {
.enter(self, x.apply_fract(new.x), y.apply_fract(new.y));
stack.push(new.node);
}
if let Some(node) = stack.last() {
node.pointer_target(self);
}
}
found_tree.clear();
}
@ -397,7 +400,7 @@ impl WlSeatGlobal {
self.focus_toplevel(n);
}
pub fn enter_popup(self: &Rc<Self>, n: &Rc<XdgPopup>) {
pub fn enter_popup(self: &Rc<Self>, _n: &Rc<XdgPopup>) {
// self.focus_xdg_surface(&n.xdg);
}

View file

@ -12,7 +12,6 @@ use crate::ifs::wl_data_device::{WlDataDevice, WlDataDeviceId};
use crate::ifs::wl_seat::wl_keyboard::{WlKeyboard, WlKeyboardId, REPEAT_INFO_SINCE};
use crate::ifs::wl_seat::wl_pointer::{WlPointer, WlPointerId};
use crate::ifs::wl_seat::wl_touch::WlTouch;
use crate::ifs::wl_surface::cursor::CursorSurface;
use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevel;
use crate::object::{Interface, Object, ObjectId};
use crate::tree::{FloatNode, FoundNode, Node};
@ -31,6 +30,7 @@ use std::io::Write;
use std::rc::Rc;
pub use types::*;
use uapi::{c, OwnedFd};
use crate::cursor::{Cursor, KnownCursor};
id!(WlSeatId);
@ -74,7 +74,7 @@ pub struct WlSeatGlobal {
kb_state: RefCell<XkbState>,
layout: Rc<OwnedFd>,
layout_size: u32,
cursor: CloneCell<Option<Rc<CursorSurface>>>,
cursor: CloneCell<Option<Rc<dyn Cursor>>>,
serial: NumCell<u32>,
}
@ -121,7 +121,21 @@ impl WlSeatGlobal {
}
}
pub fn set_cursor(&self, cursor: Option<Rc<CursorSurface>>) {
pub fn set_known_cursor(&self, cursor: KnownCursor) {
let cursors = match self.state.cursors.get() {
Some(c) => c,
None => {
self.set_cursor(None);
return;
}
};
let tpl = match cursor {
KnownCursor::Default => &cursors.default,
};
self.set_cursor(Some(tpl.instantiate()));
}
pub fn set_cursor(&self, cursor: Option<Rc<dyn Cursor>>) {
if let Some(old) = self.cursor.get() {
if let Some(new) = cursor.as_ref() {
if Rc::ptr_eq(&old, new) {
@ -130,10 +144,15 @@ impl WlSeatGlobal {
}
old.handle_unset();
}
if let Some(cursor) = cursor.as_ref() {
log::info!("setting new cursor");
let (x, y) = self.pos.get();
cursor.set_position(x.round_down(), y.round_down());
}
self.cursor.set(cursor);
}
pub fn get_cursor(&self) -> Option<Rc<CursorSurface>> {
pub fn get_cursor(&self) -> Option<Rc<dyn Cursor>> {
self.cursor.get()
}

View file

@ -8,6 +8,7 @@ use crate::object::{Interface, Object, ObjectId};
use crate::utils::buffd::MsgParser;
use std::rc::Rc;
pub use types::*;
use crate::cursor::Cursor;
const SET_CURSOR: u32 = 0;
const RELEASE: u32 = 1;
@ -153,7 +154,7 @@ impl WlPointer {
let surface = self.seat.client.get_surface(req.surface)?;
let cursor = surface.get_cursor(&self.seat.global)?;
cursor.set_hotspot(req.hotspot_x, req.hotspot_y);
cursor_opt = Some(cursor);
cursor_opt = Some(cursor as Rc<dyn Cursor>);
}
let pointer_node = match self.seat.global.pointer_stack.borrow().last().cloned() {
Some(n) => n,

View file

@ -1,8 +1,10 @@
use crate::ifs::wl_seat::WlSeatGlobal;
use crate::ifs::wl_surface::WlSurface;
use crate::rect::Rect;
use crate::render::Renderer;
use std::cell::Cell;
use std::rc::Rc;
use crate::cursor::Cursor;
pub struct CursorSurface {
seat: Rc<WlSeatGlobal>,
@ -38,15 +40,6 @@ impl CursorSurface {
);
}
pub fn set_position(&self, x: i32, y: i32) {
self.pos.set((x, y));
self.update_extents();
}
pub fn handle_unset(&self) {
self.surface.cursors.remove(&self.seat.id());
}
pub fn handle_surface_destroy(&self) {
self.seat.set_cursor(None);
}
@ -71,12 +64,23 @@ impl CursorSurface {
self.hotspot.set((hot_x - hotspot_dx, hot_y - hotspot_dy));
self.update_extents();
}
}
pub fn surface(&self) -> &Rc<WlSurface> {
&self.surface
impl Cursor for CursorSurface {
fn set_position(&self, x: i32, y: i32) {
self.pos.set((x, y));
self.update_extents();
}
pub fn extents(&self) -> Rect {
fn render(&self, renderer: &mut Renderer, x: i32, y: i32) {
renderer.render_surface(&self.surface, x, y);
}
fn extents(&self) -> Rect {
self.extents.get()
}
fn handle_unset(&self) {
self.surface.cursors.remove(&self.seat.id());
}
}

View file

@ -206,6 +206,7 @@ impl WlSurface {
}
self.set_role(SurfaceRole::Cursor)?;
let cursor = Rc::new(CursorSurface::new(seat, self));
cursor.handle_buffer_change();
self.cursors.insert(seat.id(), cursor.clone());
Ok(cursor)
}

View file

@ -4,7 +4,7 @@ use crate::client::{ClientId, DynEventFormatter};
use crate::fixed::Fixed;
use crate::ifs::wl_seat::{NodeSeatState, WlSeatGlobal};
use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceError, XdgSurfaceExt};
use crate::ifs::xdg_positioner::{XdgPositioned, XdgPositioner};
use crate::ifs::xdg_positioner::{XdgPositioned, XdgPositioner, CA};
use crate::object::{Interface, Object, ObjectId};
use crate::rect::Rect;
use crate::render::Renderer;
@ -15,6 +15,7 @@ use crate::utils::linkedlist::LinkedNode;
use std::cell::{Cell, RefCell};
use std::rc::Rc;
pub use types::*;
use crate::cursor::KnownCursor;
const DESTROY: u32 = 0;
const GRAB: u32 = 1;
@ -85,13 +86,94 @@ impl XdgPopup {
Box::new(PopupDone { obj: self.clone() })
}
fn update_relative_position(&self, parent: &XdgSurface) -> Result<(), XdgPopupError> {
let parent = parent.extents.get();
let positioner = self.pos.borrow();
if !parent.contains_rect(&positioner.ar) {
// return Err(XdgPopupError::AnchorRectOutside);
fn update_position(&self, parent: &XdgSurface) -> Result<(), XdgPopupError> {
// let parent = parent.extents.get();
let positioner = self.pos.borrow_mut();
// if !parent.contains_rect(&positioner.ar) {
// return Err(XdgPopupError::AnchorRectOutside);
// }
let parent_abs = parent.absolute_desired_extents.get();
let mut rel_pos = positioner.get_position(false, false);
let mut abs_pos = rel_pos.move_(parent_abs.x1(), parent_abs.y1());
if let Some(ws) = parent.workspace.get() {
let output_pos = ws.output.get().position.get();
let mut overflow = output_pos.get_overflow(&abs_pos);
if !overflow.is_contained() {
let mut flip_x = positioner.ca.contains(CA::FLIP_X) && overflow.x_overflow();
let mut flip_y = positioner.ca.contains(CA::FLIP_Y) && overflow.y_overflow();
if flip_x || flip_y {
let mut adj_rel = positioner.get_position(flip_x, flip_y);
let mut adj_abs = adj_rel.move_(parent_abs.x1(), parent_abs.y1());
let mut adj_overflow = output_pos.get_overflow(&adj_abs);
let mut recalculate = false;
if flip_x && adj_overflow.x_overflow() {
flip_x = false;
recalculate = true;
}
if flip_y && adj_overflow.y_overflow() {
flip_y = false;
recalculate = true;
}
if flip_x || flip_y {
if recalculate {
adj_rel = positioner.get_position(flip_x, flip_y);
adj_abs = adj_rel.move_(parent_abs.x1(), parent_abs.y1());
adj_overflow = output_pos.get_overflow(&adj_abs);
}
rel_pos = adj_rel;
abs_pos = adj_abs;
overflow = adj_overflow;
}
}
let (mut dx, mut dy) = (0, 0);
if positioner.ca.contains(CA::SLIDE_X) && overflow.x_overflow() {
dx = if overflow.left > 0 || overflow.left + overflow.right > 0 {
parent_abs.x1() - abs_pos.x1()
} else {
parent_abs.x2() - abs_pos.x2()
};
}
if positioner.ca.contains(CA::SLIDE_Y) && overflow.y_overflow() {
dy = if overflow.top > 0 || overflow.top + overflow.bottom > 0 {
parent_abs.y1() - abs_pos.y1()
} else {
parent_abs.y2() - abs_pos.y2()
};
}
if dx != 0 || dy != 0 {
rel_pos = rel_pos.move_(dx, dy);
abs_pos = rel_pos.move_(parent_abs.x1(), parent_abs.y1());
overflow = output_pos.get_overflow(&abs_pos);
}
let (mut dx1, mut dx2, mut dy1, mut dy2) = (0, 0, 0, 0);
if positioner.ca.contains(CA::RESIZE_X) {
dx1 = overflow.left.max(0);
dx2 = -overflow.right.max(0);
}
if positioner.ca.contains(CA::RESIZE_Y) {
dy1 = overflow.top.max(0);
dy2 = -overflow.bottom.max(0);
}
if dx1 > 0 || dx2 < 0 || dy1 > 0 || dy2 < 0 {
abs_pos = Rect::new(
abs_pos.x1() + dx1,
abs_pos.y1() + dy1,
abs_pos.x2() + dx2,
abs_pos.y2() + dy2,
)
.unwrap();
rel_pos = Rect::new_sized(
abs_pos.x1() - parent_abs.x1(),
abs_pos.y1() - parent_abs.y1(),
abs_pos.width(),
abs_pos.height(),
)
.unwrap();
}
}
}
self.relative_position.set(positioner.get_position());
self.relative_position.set(rel_pos);
self.xdg.absolute_desired_extents.set(abs_pos);
Ok(())
}
@ -134,7 +216,7 @@ impl XdgPopup {
.get_xdg_positioner(req.positioner)?
.value();
if let Some(parent) = self.parent.get() {
self.update_relative_position(&parent)?;
self.update_position(&parent)?;
let rel = self.relative_position.get();
self.xdg.surface.client.event(self.repositioned(req.token));
self.xdg.surface.client.event(self.configure(
@ -144,24 +226,6 @@ impl XdgPopup {
rel.height(),
));
self.xdg.send_configure();
let parent = parent.absolute_desired_extents.get();
self.xdg
.absolute_desired_extents
.set(rel.move_(parent.x1(), parent.y1()));
}
Ok(())
}
fn handle_request_(
self: &Rc<Self>,
request: u32,
parser: MsgParser<'_, '_>,
) -> Result<(), XdgPopupError> {
match request {
DESTROY => self.destroy(parser)?,
GRAB => self.grab(parser)?,
REPOSITION => self.reposition(parser)?,
_ => unreachable!(),
}
Ok(())
}
@ -171,7 +235,13 @@ impl XdgPopup {
}
}
handle_request!(XdgPopup);
handle_request! {
XdgPopup, XdgPopupError;
DESTROY => destroy,
GRAB => grab,
REPOSITION => reposition,
}
impl Object for XdgPopup {
fn id(&self) -> ObjectId {
@ -183,7 +253,11 @@ impl Object for XdgPopup {
}
fn num_requests(&self) -> u32 {
REPOSITION + 1
let last_req = match self.xdg.base.version {
0..=2 => GRAB,
_ => REPOSITION,
};
last_req + 1
}
fn break_loops(&self) {
@ -228,6 +302,10 @@ impl Node for XdgPopup {
seat.enter_popup(&self);
}
fn pointer_target(&self, seat: &Rc<WlSeatGlobal>) {
seat.set_known_cursor(KnownCursor::Default);
}
fn render(&self, renderer: &mut Renderer, x: i32, y: i32) {
renderer.render_xdg_surface(&self.xdg, x, y)
}
@ -244,7 +322,7 @@ impl Node for XdgPopup {
impl XdgSurfaceExt for XdgPopup {
fn initial_configure(self: Rc<Self>) -> Result<(), XdgSurfaceError> {
if let Some(parent) = self.parent.get() {
self.update_relative_position(&parent)?;
self.update_position(&parent)?;
let rel = self.relative_position.get();
self.xdg.surface.client.event(self.configure(
rel.x1(),
@ -252,10 +330,6 @@ impl XdgSurfaceExt for XdgPopup {
rel.width(),
rel.height(),
));
let parent = parent.absolute_desired_extents.get();
self.xdg
.absolute_desired_extents
.set(rel.move_(parent.x1(), parent.y1()));
}
Ok(())
}

View file

@ -21,6 +21,7 @@ use std::cell::{Cell, RefCell};
use std::mem;
use std::rc::Rc;
pub use types::*;
use crate::cursor::KnownCursor;
const DESTROY: u32 = 0;
const SET_PARENT: u32 = 1;
@ -395,6 +396,10 @@ impl Node for XdgToplevel {
seat.enter_toplevel(&self);
}
fn pointer_target(&self, seat: &Rc<WlSeatGlobal>) {
seat.set_known_cursor(KnownCursor::Default);
}
fn render(&self, renderer: &mut Renderer, x: i32, y: i32) {
renderer.render_xdg_surface(&self.xdg, x, y)
}

View file

@ -35,7 +35,7 @@ const BOTTOM_RIGHT: u32 = 8;
bitflags::bitflags! {
#[derive(Default)]
pub struct Square: u32 {
pub struct Edge: u32 {
const TOP = 1 << 0;
const BOTTOM = 1 << 1;
const LEFT = 1 << 2;
@ -43,18 +43,18 @@ bitflags::bitflags! {
}
}
impl Square {
impl Edge {
fn from_enum(e: u32) -> Option<Self> {
let s = match e {
NONE => Square::empty(),
TOP => Square::TOP,
BOTTOM => Square::BOTTOM,
LEFT => Square::LEFT,
RIGHT => Square::RIGHT,
TOP_LEFT => Square::TOP | Square::LEFT,
BOTTOM_LEFT => Square::BOTTOM | Square::LEFT,
TOP_RIGHT => Square::TOP | Square::RIGHT,
BOTTOM_RIGHT => Square::BOTTOM | Square::RIGHT,
NONE => Edge::empty(),
TOP => Edge::TOP,
BOTTOM => Edge::BOTTOM,
LEFT => Edge::LEFT,
RIGHT => Edge::RIGHT,
TOP_LEFT => Edge::TOP | Edge::LEFT,
BOTTOM_LEFT => Edge::BOTTOM | Edge::LEFT,
TOP_RIGHT => Edge::TOP | Edge::RIGHT,
BOTTOM_RIGHT => Edge::BOTTOM | Edge::RIGHT,
_ => return None,
};
Some(s)
@ -88,8 +88,8 @@ pub struct XdgPositioned {
pub size_width: i32,
pub size_height: i32,
pub ar: Rect,
pub anchor: Square,
pub gravity: Square,
pub anchor: Edge,
pub gravity: Edge,
pub ca: CA,
pub off_x: i32,
pub off_y: i32,
@ -104,35 +104,46 @@ impl XdgPositioned {
self.size_height != 0 && self.size_width != 0
}
pub fn get_position(&self) -> Rect {
pub fn get_position(&self, flip_x: bool, flip_y: bool) -> Rect {
let mut anchor = self.anchor;
let mut gravity = self.gravity;
if flip_x {
anchor ^= Edge::LEFT | Edge::RIGHT;
gravity ^= Edge::LEFT | Edge::RIGHT;
}
if flip_y {
anchor ^= Edge::TOP | Edge::BOTTOM;
gravity ^= Edge::TOP | Edge::BOTTOM;
}
let mut x1 = self.off_x;
let mut y1 = self.off_x;
if self.anchor.contains(Square::LEFT) {
if anchor.contains(Edge::LEFT) {
x1 += self.ar.x1();
} else if self.anchor.contains(Square::RIGHT) {
} else if anchor.contains(Edge::RIGHT) {
x1 += self.ar.x2();
} else {
x1 += self.ar.x1() + self.ar.width() / 2;
}
if self.anchor.contains(Square::TOP) {
if anchor.contains(Edge::TOP) {
y1 += self.ar.y1();
} else if self.anchor.contains(Square::BOTTOM) {
} else if anchor.contains(Edge::BOTTOM) {
y1 += self.ar.y2();
} else {
y1 += self.ar.y1() + self.ar.height() / 2;
}
if self.gravity.contains(Square::LEFT) {
if gravity.contains(Edge::LEFT) {
x1 -= self.size_width;
} else if !self.gravity.contains(Square::RIGHT) {
} else if !gravity.contains(Edge::RIGHT) {
x1 -= self.size_width / 2;
}
if self.gravity.contains(Square::TOP) {
if gravity.contains(Edge::TOP) {
y1 -= self.size_height;
} else if !self.gravity.contains(Square::BOTTOM) {
} else if !gravity.contains(Edge::BOTTOM) {
y1 -= self.size_height / 2;
}
@ -193,7 +204,7 @@ impl XdgPositioner {
fn set_anchor(&self, parser: MsgParser<'_, '_>) -> Result<(), SetAnchorError> {
let req: SetAnchor = self.client.parse(self, parser)?;
let anchor = match Square::from_enum(req.anchor) {
let anchor = match Edge::from_enum(req.anchor) {
Some(a) => a,
_ => return Err(SetAnchorError::UnknownAnchor(req.anchor)),
};
@ -203,7 +214,7 @@ impl XdgPositioner {
fn set_gravity(&self, parser: MsgParser<'_, '_>) -> Result<(), SetGravityError> {
let req: SetGravity = self.client.parse(self, parser)?;
let gravity = match Square::from_enum(req.gravity) {
let gravity = match Edge::from_enum(req.gravity) {
Some(a) => a,
_ => return Err(SetGravityError::UnknownGravity(req.gravity)),
};