1
0
Fork 0
forked from wry/wry

autocommit 2022-02-09 17:26:50 CET

This commit is contained in:
Julian Orth 2022-02-09 17:26:50 +01:00
parent 4190b910f8
commit 8faab3fe53
25 changed files with 1081 additions and 316 deletions

View file

@ -1,14 +1,17 @@
use crate::client::{Client, ClientError};
use crate::ifs::ipc::wl_data_device::WlDataDevice;
use crate::ifs::ipc::wl_data_offer::WlDataOffer;
use crate::ifs::ipc::{add_mime_type, break_source_loops, cancel_offers, destroy_source, OFFER_STATE_ACCEPTED, OFFER_STATE_DROPPED, SharedState, SourceData};
use crate::object::Object;
use crate::utils::buffd::MsgParser;
use crate::utils::buffd::MsgParserError;
use crate::wire::wl_data_source::*;
use crate::wire::{WlDataSourceId};
use crate::wire::WlDataSourceId;
use std::rc::Rc;
use thiserror::Error;
use uapi::OwnedFd;
use crate::ifs::ipc::{add_mime_type, disconnect_source, SourceData};
use crate::ifs::ipc::wl_data_device::WlDataDevice;
use crate::ifs::ipc::wl_data_device_manager::{DND_ALL, DND_NONE};
use crate::utils::bitflags::BitflagsExt;
#[allow(dead_code)]
const INVALID_ACTION_MASK: u32 = 0;
@ -28,6 +31,61 @@ impl WlDataSource {
}
}
pub fn on_leave(&self) {
if self.data.shared.get().state.get().contains(OFFER_STATE_DROPPED) {
return;
}
self.data.shared.set(Rc::new(SharedState::default()));
self.send_target(None);
self.send_action(DND_NONE);
cancel_offers::<WlDataDevice>(self);
}
pub fn update_selected_action(&self) {
let shared = self.data.shared.get();
let server_actions = match self.data.actions.get() {
Some(n) => n,
_ => {
log::error!("Server actions not set");
return;
}
};
let actions = server_actions & shared.receiver_actions.get();
let action = if actions.contains(shared.receiver_preferred_action.get()) {
shared.receiver_preferred_action.get()
} else if actions != 0 {
1 << actions.trailing_zeros()
} else {
0
};
log::info!("sa = {}, ra = {}, action = {}", server_actions, shared.receiver_actions.get(), action);
if shared.selected_action.replace(action) != action {
for (_, offer) in &self.data.offers {
offer.send_action(action);
offer.client.flush();
}
self.send_action(action);
self.data.client.flush();
}
}
pub fn for_each_data_offer<C: FnMut(&WlDataOffer)>(&self, mut f: C) {
for (_, offer) in &self.data.offers {
f(&offer);
}
}
pub fn can_drop(&self) -> bool {
let shared = self.data.shared.get();
shared.selected_action.get() != 0 && shared.state.get().contains(OFFER_STATE_ACCEPTED)
}
pub fn on_drop(&self) {
self.send_dnd_drop_performed();
let shared = self.data.shared.get();
shared.state.or_assign(OFFER_STATE_DROPPED);
}
pub fn send_cancelled(&self) {
self.data.client.event(Cancelled { self_id: self.id })
}
@ -40,6 +98,25 @@ impl WlDataSource {
})
}
pub fn send_target(&self, mime_type: Option<&str>) {
self.data.client.event(Target {
self_id: self.id,
mime_type,
})
}
pub fn send_dnd_finished(&self) {
self.data.client.event(DndFinished { self_id: self.id })
}
pub fn send_action(&self, dnd_action: u32) {
self.data.client.event(Action { self_id: self.id, dnd_action, })
}
pub fn send_dnd_drop_performed(&self) {
self.data.client.event(DndDropPerformed { self_id: self.id })
}
fn offer(&self, parser: MsgParser<'_, '_>) -> Result<(), OfferError> {
let req: Offer = self.data.client.parse(self, parser)?;
add_mime_type::<WlDataDevice>(self, req.mime_type);
@ -48,13 +125,20 @@ impl WlDataSource {
fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
let _req: Destroy = self.data.client.parse(self, parser)?;
disconnect_source::<WlDataDevice>(self);
destroy_source::<WlDataDevice>(self);
self.data.client.remove_obj(self)?;
Ok(())
}
fn set_actions(&self, parser: MsgParser<'_, '_>) -> Result<(), SetActionsError> {
let _req: SetActions = self.data.client.parse(self, parser)?;
let req: SetActions = self.data.client.parse(self, parser)?;
if self.data.actions.get().is_some() {
return Err(SetActionsError::AlreadySet);
}
if req.dnd_actions & !DND_ALL != 0 {
return Err(SetActionsError::InvalidActions);
}
self.data.actions.set(Some(req.dnd_actions));
Ok(())
}
}
@ -73,7 +157,7 @@ impl Object for WlDataSource {
}
fn break_loops(&self) {
disconnect_source::<WlDataDevice>(self);
break_source_loops::<WlDataDevice>(self);
}
}
@ -118,6 +202,10 @@ pub enum SetActionsError {
ParseFailed(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
#[error("The set of actions is invalid")]
InvalidActions,
#[error("The actions have already been set")]
AlreadySet,
}
efrom!(SetActionsError, ParseFailed, MsgParserError);
efrom!(SetActionsError, ClientError);