1
0
Fork 0
forked from wry/wry

autocommit 2022-02-05 02:07:07 CET

This commit is contained in:
Julian Orth 2022-02-05 02:07:07 +01:00
parent 89bfd2ffcd
commit 2d8b3a200e
21 changed files with 328 additions and 87 deletions

View file

@ -1,9 +1,9 @@
mod types;
use crate::client::{Client, DynEventFormatter};
use crate::client::{DynEventFormatter};
use crate::ifs::wl_data_device_manager::WlDataDeviceManagerObj;
use crate::ifs::wl_data_offer::WlDataOfferId;
use crate::ifs::wl_seat::WlSeatObj;
use crate::ifs::wl_seat::{WlSeatObj};
use crate::object::{Interface, Object, ObjectId};
use crate::utils::buffd::MsgParser;
use std::rc::Rc;
@ -28,7 +28,6 @@ id!(WlDataDeviceId);
pub struct WlDataDevice {
pub id: WlDataDeviceId,
pub manager: Rc<WlDataDeviceManagerObj>,
client: Rc<Client>,
seat: Rc<WlSeatObj>,
}
@ -41,11 +40,17 @@ impl WlDataDevice {
Self {
id,
manager: manager.clone(),
client: seat.client().clone(),
seat: seat.clone(),
}
}
pub fn data_offer(self: &Rc<Self>, id: WlDataOfferId) -> DynEventFormatter {
Box::new(DataOffer {
obj: self.clone(),
id,
})
}
pub fn selection(self: &Rc<Self>, id: WlDataOfferId) -> DynEventFormatter {
Box::new(Selection {
obj: self.clone(),
@ -54,19 +59,25 @@ impl WlDataDevice {
}
fn start_drag(&self, parser: MsgParser<'_, '_>) -> Result<(), StartDragError> {
let _req: StartDrag = self.client.parse(self, parser)?;
let _req: StartDrag = self.manager.client.parse(self, parser)?;
Ok(())
}
fn set_selection(&self, parser: MsgParser<'_, '_>) -> Result<(), SetSelectionError> {
let _req: SetSelection = self.client.parse(self, parser)?;
let req: SetSelection = self.manager.client.parse(self, parser)?;
let src = if req.source.is_none() {
None
} else {
Some(self.manager.client.get_wl_data_source(req.source)?)
};
self.seat.global.set_selection(src)?;
Ok(())
}
fn release(&self, parser: MsgParser<'_, '_>) -> Result<(), ReleaseError> {
let _req: Release = self.client.parse(self, parser)?;
let _req: Release = self.manager.client.parse(self, parser)?;
self.seat.remove_data_device(self);
self.client.remove_obj(self)?;
self.manager.client.remove_obj(self)?;
Ok(())
}

View file

@ -2,7 +2,7 @@ use crate::client::{ClientError, EventFormatter, RequestParser};
use crate::fixed::Fixed;
use crate::ifs::wl_data_device::{WlDataDevice, DATA_OFFER, DROP, ENTER, LEAVE, MOTION, SELECTION};
use crate::ifs::wl_data_offer::WlDataOfferId;
use crate::ifs::wl_data_source::WlDataSourceId;
use crate::ifs::wl_data_source::{WlDataSourceError, WlDataSourceId};
use crate::ifs::wl_surface::WlSurfaceId;
use crate::object::Object;
use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError};
@ -39,9 +39,12 @@ pub enum SetSelectionError {
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
#[error(transparent)]
WlDataSourceError(Box<WlDataSourceError>),
}
efrom!(SetSelectionError, ParseFailed, MsgParserError);
efrom!(SetSelectionError, ClientError);
efrom!(SetSelectionError, WlDataSourceError);
#[derive(Debug, Error)]
pub enum ReleaseError {

View file

@ -28,8 +28,8 @@ pub struct WlDataDeviceManagerGlobal {
}
pub struct WlDataDeviceManagerObj {
id: WlDataDeviceManagerId,
client: Rc<Client>,
pub id: WlDataDeviceManagerId,
pub client: Rc<Client>,
pub version: u32,
}

View file

@ -1,8 +1,12 @@
mod types;
use crate::client::Client;
use crate::client::{Client, DynEventFormatter};
use crate::ifs::wl_data_source::{WlDataSource};
use crate::ifs::wl_seat::WlSeatGlobal;
use crate::object::{Interface, Object, ObjectId};
use crate::utils::buffd::MsgParser;
use crate::utils::clonecell::CloneCell;
use std::ops::Deref;
use std::rc::Rc;
pub use types::*;
@ -27,24 +31,83 @@ const INVALID_OFFER: u32 = 3;
id!(WlDataOfferId);
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum DataOfferRole {
Selection,
}
pub struct WlDataOffer {
id: WlDataOfferId,
client: Rc<Client>,
pub id: WlDataOfferId,
pub client: Rc<Client>,
pub role: DataOfferRole,
pub source: CloneCell<Option<Rc<WlDataSource>>>,
}
impl WlDataOffer {
pub fn create(
client: &Rc<Client>,
role: DataOfferRole,
src: &Rc<WlDataSource>,
seat: &Rc<WlSeatGlobal>,
) -> Option<Rc<Self>> {
let id = match client.new_id() {
Ok(id) => id,
Err(e) => {
client.error(e);
return None;
}
};
let slf = Rc::new(Self {
id,
client: client.clone(),
role,
source: CloneCell::new(Some(src.clone())),
});
let mt = src.mime_types.borrow_mut();
seat.for_each_data_device(0, client.id, |device| {
client.event(device.data_offer(slf.id));
for mt in mt.deref() {
client.event(slf.offer(mt));
}
let ev = match role {
DataOfferRole::Selection => device.selection(id),
};
client.event(ev);
});
client.add_server_obj(&slf);
Some(slf)
}
pub fn offer(self: &Rc<Self>, mime_type: &str) -> DynEventFormatter {
Box::new(Offer {
obj: self.clone(),
mime_type: mime_type.to_string(),
})
}
fn accept(&self, parser: MsgParser<'_, '_>) -> Result<(), AcceptError> {
let _req: Accept = self.client.parse(self, parser)?;
Ok(())
}
fn receive(&self, parser: MsgParser<'_, '_>) -> Result<(), ReceiveError> {
let _req: Receive = self.client.parse(self, parser)?;
let req: Receive = self.client.parse(self, parser)?;
if let Some(src) = self.source.get() {
src.client.event(src.send(req.mime_type, req.fd));
src.client.flush();
}
Ok(())
}
fn disconnect(&self) {
if let Some(src) = self.source.set(None) {
src.destroy_offer();
}
}
fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
let _req: Destroy = self.client.parse(self, parser)?;
self.disconnect();
self.client.remove_obj(self)?;
Ok(())
}
@ -90,4 +153,8 @@ impl Object for WlDataOffer {
fn num_requests(&self) -> u32 {
SET_ACTIONS + 1
}
fn break_loops(&self) {
self.disconnect();
}
}

View file

@ -2,7 +2,7 @@ use crate::client::{ClientError, EventFormatter, RequestParser};
use crate::ifs::wl_data_offer::{WlDataOffer, ACTION, OFFER, SOURCE_ACTIONS};
use crate::object::Object;
use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError};
use bstr::{BStr, BString};
use bstr::{BStr};
use std::fmt::{Debug, Formatter};
use std::rc::Rc;
use thiserror::Error;
@ -83,7 +83,7 @@ impl<'a> RequestParser<'a> for Accept<'a> {
fn parse(parser: &mut MsgParser<'_, 'a>) -> Result<Self, MsgParserError> {
Ok(Self {
serial: parser.uint()?,
mime_type: parser.string()?,
mime_type: parser.bstr()?,
})
}
}
@ -98,13 +98,13 @@ impl Debug for Accept<'_> {
}
pub(super) struct Receive<'a> {
pub mime_type: &'a BStr,
pub mime_type: &'a str,
pub fd: OwnedFd,
}
impl<'a> RequestParser<'a> for Receive<'a> {
fn parse(parser: &mut MsgParser<'_, 'a>) -> Result<Self, MsgParserError> {
Ok(Self {
mime_type: parser.string()?,
mime_type: parser.str()?,
fd: parser.fd()?,
})
}
@ -168,7 +168,7 @@ impl Debug for SetActions {
pub(super) struct Offer {
pub obj: Rc<WlDataOffer>,
pub mime_type: BString,
pub mime_type: String,
}
impl EventFormatter for Offer {
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {

View file

@ -1,9 +1,15 @@
mod types;
use crate::client::Client;
use crate::client::{Client, DynEventFormatter};
use crate::ifs::wl_data_offer::{DataOfferRole, WlDataOffer};
use crate::ifs::wl_seat::WlSeatGlobal;
use crate::object::{Interface, Object, ObjectId};
use crate::utils::buffd::MsgParser;
use crate::utils::clonecell::{CloneCell, UnsafeCellCloneSafe};
use ahash::AHashSet;
use std::cell::RefCell;
use std::rc::Rc;
use uapi::OwnedFd;
pub use types::*;
const OFFER: u32 = 0;
@ -24,9 +30,20 @@ const INVALID_SOURCE: u32 = 1;
id!(WlDataSourceId);
#[derive(Clone)]
struct Attachment {
seat: Rc<WlSeatGlobal>,
role: DataOfferRole,
}
unsafe impl UnsafeCellCloneSafe for Attachment {}
pub struct WlDataSource {
id: WlDataSourceId,
client: Rc<Client>,
pub id: WlDataSourceId,
pub client: Rc<Client>,
pub mime_types: RefCell<AHashSet<String>>,
attachment: CloneCell<Option<Attachment>>,
offer: CloneCell<Option<Rc<WlDataOffer>>>,
}
impl WlDataSource {
@ -34,16 +51,101 @@ impl WlDataSource {
Self {
id,
client: client.clone(),
mime_types: RefCell::new(Default::default()),
attachment: Default::default(),
offer: Default::default(),
}
}
fn offer(&self, parser: MsgParser<'_, '_>) -> Result<(), OfferError> {
let _req: Offer = self.client.parse(self, parser)?;
pub fn attach(
&self,
seat: &Rc<WlSeatGlobal>,
role: DataOfferRole,
) -> Result<(), WlDataSourceError> {
let old = self.attachment.set(
Some(Attachment {
seat: seat.clone(),
role,
}),
);
if old.is_some() {
return Err(WlDataSourceError::AlreadyAttached);
}
Ok(())
}
pub fn detach(self: &Rc<Self>) {
self.attachment.set(None);
if let Some(offer) = self.offer.set(None) {
offer.source.set(None);
}
self.client.event(self.cancelled());
self.client.flush();
}
pub fn create_offer(self: &Rc<Self>, client: &Rc<Client>) {
let attachment = match self.attachment.get() {
Some(a) => a,
_ => {
log::error!("Trying to create an offer from a unattached data source");
return;
}
};
let offer = WlDataOffer::create(client, attachment.role, self, &attachment.seat);
let old = self.offer.set(offer);
if let Some(offer) = old {
offer.source.set(None);
}
}
pub fn destroy_offer(&self) {
self.offer.take();
}
pub fn cancelled(self: &Rc<Self>) -> DynEventFormatter {
Box::new(Cancelled {
obj: self.clone(),
})
}
pub fn send(self: &Rc<Self>, mime_type: &str, fd: OwnedFd) -> DynEventFormatter {
Box::new(Send {
obj: self.clone(),
mime_type: mime_type.to_string(),
fd: Rc::new(fd),
})
}
fn offer(&self, parser: MsgParser<'_, '_>) -> Result<(), OfferError> {
let req: Offer = self.client.parse(self, parser)?;
if self
.mime_types
.borrow_mut()
.insert(req.mime_type.to_string())
{
if let Some(offer) = self.offer.get() {
offer.client.event(offer.offer(req.mime_type));
}
}
Ok(())
}
fn disconnect(&self) {
if let Some(offer) = self.offer.take() {
offer.source.set(None);
}
if let Some(attachment) = self.attachment.get() {
match attachment.role {
DataOfferRole::Selection => {
let _ = attachment.seat.set_selection(None);
},
}
}
}
fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
let _req: Destroy = self.client.parse(self, parser)?;
self.disconnect();
self.client.remove_obj(self)?;
Ok(())
}
@ -82,4 +184,8 @@ impl Object for WlDataSource {
fn num_requests(&self) -> u32 {
SET_ACTIONS + 1
}
fn break_loops(&self) {
self.disconnect();
}
}

View file

@ -4,7 +4,7 @@ use crate::ifs::wl_data_source::{
};
use crate::object::Object;
use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError};
use bstr::{BStr, BString};
use bstr::{BString};
use std::fmt::{Debug, Formatter};
use std::rc::Rc;
use thiserror::Error;
@ -20,6 +20,8 @@ pub enum WlDataSourceError {
DestroyError(#[from] DestroyError),
#[error("Could not process `set_actions` request")]
SetActionsError(#[from] SetActionsError),
#[error("The data source is already attached")]
AlreadyAttached,
}
efrom!(WlDataSourceError, ClientError);
@ -54,12 +56,12 @@ efrom!(SetActionsError, ParseFailed, MsgParserError);
efrom!(SetActionsError, ClientError);
pub(super) struct Offer<'a> {
pub mime_type: &'a BStr,
pub mime_type: &'a str,
}
impl<'a> RequestParser<'a> for Offer<'a> {
fn parse(parser: &mut MsgParser<'_, 'a>) -> Result<Self, MsgParserError> {
Ok(Self {
mime_type: parser.string()?,
mime_type: parser.str()?,
})
}
}
@ -117,7 +119,7 @@ impl Debug for Target {
pub(super) struct Send {
pub obj: Rc<WlDataSource>,
pub mime_type: BString,
pub mime_type: String,
pub fd: Rc<OwnedFd>,
}
impl EventFormatter for Send {

View file

@ -101,7 +101,7 @@ impl<'a> RequestParser<'a> for Bind<'a> {
fn parse(parser: &mut MsgParser<'_, 'a>) -> Result<Self, MsgParserError> {
Ok(Self {
name: parser.global()?,
interface: parser.string()?,
interface: parser.bstr()?,
version: parser.uint()?,
id: parser.object()?,
})

View file

@ -2,7 +2,7 @@ use crate::backend::{KeyState, OutputId, ScrollAxis, SeatEvent, SeatId};
use crate::client::{ClientId, DynEventFormatter};
use crate::fixed::Fixed;
use crate::ifs::wl_data_device::WlDataDevice;
use crate::ifs::wl_data_offer::WlDataOfferId;
use crate::ifs::wl_data_offer::{WlDataOfferId};
use crate::ifs::wl_seat::wl_keyboard::WlKeyboard;
use crate::ifs::wl_seat::wl_pointer::{WlPointer, POINTER_FRAME_SINCE_VERSION};
use crate::ifs::wl_seat::{
@ -241,7 +241,18 @@ impl WlSeatGlobal {
k.modifiers(serial, mods_depressed, mods_latched, mods_locked, group)
});
self.surface_data_device_event(0, &surface, |dd| dd.selection(WlDataOfferId::NONE));
if old.client_id() != Some(surface.client.id) {
match self.selection.get() {
None => {
self.surface_data_device_event(0, &surface, |dd| {
dd.selection(WlDataOfferId::NONE)
});
}
Some(sel) => {
sel.create_offer(&surface.client);
}
}
}
}
fn for_each_seat<C>(&self, ver: u32, client: ClientId, mut f: C)
@ -282,7 +293,7 @@ impl WlSeatGlobal {
})
}
fn for_each_data_device<C>(&self, ver: u32, client: ClientId, mut f: C)
pub fn for_each_data_device<C>(&self, ver: u32, client: ClientId, mut f: C)
where
C: FnMut(&Rc<WlDataDevice>),
{

View file

@ -10,6 +10,8 @@ use crate::cursor::{Cursor, KnownCursor};
use crate::fixed::Fixed;
use crate::globals::{Global, GlobalName};
use crate::ifs::wl_data_device::{WlDataDevice, WlDataDeviceId};
use crate::ifs::wl_data_offer::{DataOfferRole, WlDataOfferId};
use crate::ifs::wl_data_source::{WlDataSource, WlDataSourceError};
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;
@ -95,6 +97,7 @@ pub struct WlSeatGlobal {
serial: NumCell<u32>,
grabber: RefCell<Option<PointerGrabber>>,
tree_changed: Rc<AsyncEvent>,
selection: CloneCell<Option<Rc<WlDataSource>>>,
}
impl WlSeatGlobal {
@ -144,20 +147,31 @@ impl WlSeatGlobal {
serial: Default::default(),
grabber: RefCell::new(None),
tree_changed: tree_changed.clone(),
selection: Default::default(),
}
}
// pub fn grab_pointer(self: &Rc<Self>, node: Rc<dyn Node>) -> Option<PointerGrab> {
// let mut grabber = self.grabber.borrow_mut();
// if grabber.is_some() {
// return None;
// }
// *grabber = Some(PointerGrabber {
// node,
// buttons: Default::default(),
// });
// Some(PointerGrab { seat: self.clone() })
// }
pub fn set_selection(self: &Rc<Self>, selection: Option<Rc<WlDataSource>>) -> Result<(), WlDataSourceError> {
if let Some(new) = &selection {
new.attach(self, DataOfferRole::Selection)?;
}
if let Some(old) = self.selection.set(selection.clone()) {
old.detach();
}
if let Some(client) = self.keyboard_node.get().client() {
match selection {
Some(sel) => {
sel.create_offer(&client);
}
_ => {
self.for_each_data_device(0, client.id, |device| {
client.event(device.selection(WlDataOfferId::NONE));
});
}
}
}
Ok(())
}
pub fn set_known_cursor(&self, cursor: KnownCursor) {
let cursors = match self.state.cursors.get() {
@ -292,10 +306,6 @@ impl WlSeatObj {
}
}
pub fn client(&self) -> &Rc<Client> {
&self.client
}
pub fn move_(&self, node: &Rc<FloatNode>) {
self.global.move_(node);
}

View file

@ -4,7 +4,7 @@ pub mod wl_subsurface;
pub mod xdg_surface;
use crate::backend::{KeyState, ScrollAxis, SeatId};
use crate::client::{Client, ClientId, DynEventFormatter, RequestParser};
use crate::client::{Client, DynEventFormatter, RequestParser};
use crate::fixed::Fixed;
use crate::ifs::wl_buffer::WlBuffer;
use crate::ifs::wl_callback::WlCallback;
@ -17,7 +17,9 @@ use crate::object::{Interface, Object, ObjectId};
use crate::pixman::Region;
use crate::rect::Rect;
use crate::render::Renderer;
use crate::tree::{Node, NodeId};
use crate::tree::{
Node, NodeId,
};
use crate::utils::buffd::{MsgParser, MsgParserError};
use crate::utils::clonecell::CloneCell;
use crate::utils::linkedlist::LinkedList;
@ -662,7 +664,7 @@ impl Node for WlSurface {
renderer.render_surface(self, x, y);
}
fn client_id(&self) -> Option<ClientId> {
Some(self.client.id)
fn client(&self) -> Option<Rc<Client>> {
Some(self.client.clone())
}
}

View file

@ -1,6 +1,6 @@
mod types;
use crate::client::{ClientId, DynEventFormatter};
use crate::client::{Client, DynEventFormatter};
use crate::cursor::KnownCursor;
use crate::fixed::Fixed;
use crate::ifs::wl_seat::{NodeSeatState, WlSeatGlobal};
@ -311,8 +311,8 @@ impl Node for XdgPopup {
self.xdg.set_workspace(ws);
}
fn client_id(&self) -> Option<ClientId> {
Some(self.xdg.surface.client.id)
fn client(&self) -> Option<Rc<Client>> {
Some(self.xdg.surface.client.clone())
}
}

View file

@ -2,7 +2,7 @@ mod types;
use crate::backend::SeatId;
use crate::bugs::Bugs;
use crate::client::{ClientId, DynEventFormatter};
use crate::client::{Client, DynEventFormatter};
use crate::cursor::KnownCursor;
use crate::fixed::Fixed;
use crate::ifs::wl_seat::{NodeSeatState, WlSeatGlobal};
@ -496,8 +496,8 @@ impl Node for XdgToplevel {
self.xdg.set_workspace(ws);
}
fn client_id(&self) -> Option<ClientId> {
Some(self.xdg.surface.client.id)
fn client(&self) -> Option<Rc<Client>> {
Some(self.xdg.surface.client.clone())
}
}

View file

@ -219,7 +219,7 @@ pub(super) struct SetTitle<'a> {
impl<'a> RequestParser<'a> for SetTitle<'a> {
fn parse(parser: &mut MsgParser<'_, 'a>) -> Result<Self, MsgParserError> {
Ok(Self {
title: parser.string()?,
title: parser.bstr()?,
})
}
}
@ -235,7 +235,7 @@ pub(super) struct SetAppId<'a> {
impl<'a> RequestParser<'a> for SetAppId<'a> {
fn parse(parser: &mut MsgParser<'_, 'a>) -> Result<Self, MsgParserError> {
Ok(Self {
app_id: parser.string()?,
app_id: parser.bstr()?,
})
}
}