wip: screencopy

This commit is contained in:
Victoria Brekenfeld 2022-11-03 18:51:27 +01:00
parent dd100d65e4
commit 5a4df346a8
26 changed files with 2046 additions and 327 deletions

View file

@ -203,7 +203,7 @@ impl CosmicMapped {
pub fn set_tiled(&self, tiled: bool) {
for toplevel in match &self.element {
// we use the tiled state of stack windows anyway to get rid of decorations
CosmicMappedInternal::Stack(s) => None,
CosmicMappedInternal::Stack(_) => None,
CosmicMappedInternal::Window(w) => Some(w.window.toplevel()),
_ => unreachable!(),
} {

View file

@ -1,4 +1,7 @@
use crate::state::State;
use crate::{
state::State, utils::prelude::SeatExt, wayland::handlers::screencopy::ScreencopySessions,
};
use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_session_v1::InputType;
use smithay::{
backend::{
input::KeyState,
@ -29,6 +32,9 @@ use std::{
pub struct CosmicStack {
windows: Arc<Mutex<Vec<Window>>>,
active: Arc<AtomicUsize>,
last_location: Arc<Mutex<Option<(Point<f64, Logical>, Serial, u32)>>>,
previous_keyboard: Arc<AtomicUsize>,
previous_pointer: Arc<AtomicUsize>,
pub(super) header: Arc<Mutex<Option<HeaderBar>>>,
}
@ -68,7 +74,9 @@ impl CosmicStack {
.iter()
.position(|w| w == window)
{
self.active.store(val, Ordering::SeqCst)
let old = self.active.swap(val, Ordering::SeqCst);
self.previous_keyboard.store(old, Ordering::SeqCst);
self.previous_pointer.store(old, Ordering::SeqCst);
}
}
@ -92,6 +100,69 @@ impl CosmicStack {
};
}
}
fn keyboard_leave_if_previous(
&self,
seat: &Seat<State>,
data: &mut State,
serial: Serial,
) -> usize {
let active = self.active.load(Ordering::SeqCst);
let previous = self.previous_keyboard.swap(active, Ordering::SeqCst);
if previous != active {
KeyboardTarget::leave(&self.windows.lock().unwrap()[previous], seat, data, serial);
// TODO: KeyboardTarget::enter(&self.windows.lock().unwrap()[active], seat, data, serial, seat.keys())
}
active
}
fn pointer_leave_if_previous(
&self,
seat: &Seat<State>,
data: &mut State,
serial: Serial,
time: u32,
location: Point<f64, Logical>,
) -> usize {
let active = self.active.load(Ordering::SeqCst);
let previous = self.previous_pointer.swap(active, Ordering::SeqCst);
if previous != active {
if let Some(sessions) = self.windows.lock().unwrap()[previous]
.user_data()
.get::<ScreencopySessions>()
{
for session in &*sessions.0.borrow() {
session.cursor_leave(seat, InputType::Pointer)
}
}
PointerTarget::leave(
&self.windows.lock().unwrap()[previous],
seat,
data,
serial,
time,
);
if let Some(sessions) = self.windows.lock().unwrap()[active]
.user_data()
.get::<ScreencopySessions>()
{
for session in &*sessions.0.borrow() {
session.cursor_enter(seat, InputType::Pointer)
}
}
PointerTarget::enter(
&self.windows.lock().unwrap()[active],
seat,
data,
&MotionEvent {
location,
serial,
time,
},
);
}
active
}
}
impl IsAlive for CosmicStack {
@ -158,6 +229,8 @@ impl KeyboardTarget<State> for CosmicStack {
keys: Vec<KeysymHandle<'_>>,
serial: Serial,
) {
let active = self.active.load(Ordering::SeqCst);
self.previous_keyboard.store(active, Ordering::SeqCst);
KeyboardTarget::enter(
&self.windows.lock().unwrap()[self.active.load(Ordering::SeqCst)],
seat,
@ -167,12 +240,8 @@ impl KeyboardTarget<State> for CosmicStack {
)
}
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial) {
KeyboardTarget::leave(
&self.windows.lock().unwrap()[self.active.load(Ordering::SeqCst)],
seat,
data,
serial,
)
let active = self.keyboard_leave_if_previous(seat, data, serial);
KeyboardTarget::leave(&self.windows.lock().unwrap()[active], seat, data, serial)
}
fn key(
&self,
@ -183,8 +252,9 @@ impl KeyboardTarget<State> for CosmicStack {
serial: Serial,
time: u32,
) {
let active = self.keyboard_leave_if_previous(seat, data, serial);
KeyboardTarget::key(
&self.windows.lock().unwrap()[self.active.load(Ordering::SeqCst)],
&self.windows.lock().unwrap()[active],
seat,
data,
key,
@ -200,8 +270,9 @@ impl KeyboardTarget<State> for CosmicStack {
modifiers: ModifiersState,
serial: Serial,
) {
let active = self.keyboard_leave_if_previous(seat, data, serial);
KeyboardTarget::modifiers(
&self.windows.lock().unwrap()[self.active.load(Ordering::SeqCst)],
&self.windows.lock().unwrap()[active],
seat,
data,
modifiers,
@ -212,6 +283,16 @@ impl KeyboardTarget<State> for CosmicStack {
impl PointerTarget<State> for CosmicStack {
fn enter(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) {
if let Some(sessions) = self.active().user_data().get::<ScreencopySessions>() {
for session in &*sessions.0.borrow() {
session.cursor_enter(seat, InputType::Pointer)
}
}
*self.last_location.lock().unwrap() = Some((event.location, event.serial, event.time));
let active = self.active.load(Ordering::SeqCst);
self.previous_pointer.store(active, Ordering::SeqCst);
PointerTarget::enter(
&self.windows.lock().unwrap()[self.active.load(Ordering::SeqCst)],
seat,
@ -220,14 +301,27 @@ impl PointerTarget<State> for CosmicStack {
)
}
fn motion(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) {
PointerTarget::motion(
&self.windows.lock().unwrap()[self.active.load(Ordering::SeqCst)],
seat,
data,
event,
)
let active =
self.pointer_leave_if_previous(seat, data, event.serial, event.time, event.location);
if let Some(sessions) = self.active().user_data().get::<ScreencopySessions>() {
for session in &*sessions.0.borrow() {
let buffer_loc = (event.location.x, event.location.y); // we always screencast windows at 1x1 scale
if let Some((geo, hotspot)) =
seat.cursor_geometry(buffer_loc, &data.common.start_time)
{
session.cursor_info(seat, InputType::Pointer, geo, hotspot);
}
}
}
PointerTarget::motion(&self.windows.lock().unwrap()[active], seat, data, event)
}
fn button(&self, seat: &Seat<State>, data: &mut State, event: &ButtonEvent) {
if let Some((location, _serial, _time)) = self.last_location.lock().unwrap().clone() {
self.pointer_leave_if_previous(seat, data, event.serial, event.time, location);
}
PointerTarget::button(
&self.windows.lock().unwrap()[self.active.load(Ordering::SeqCst)],
seat,
@ -236,6 +330,10 @@ impl PointerTarget<State> for CosmicStack {
)
}
fn axis(&self, seat: &Seat<State>, data: &mut State, frame: AxisFrame) {
if let Some((location, serial, time)) = self.last_location.lock().unwrap().clone() {
self.pointer_leave_if_previous(seat, data, serial, time, location);
}
PointerTarget::axis(
&self.windows.lock().unwrap()[self.active.load(Ordering::SeqCst)],
seat,
@ -244,6 +342,15 @@ impl PointerTarget<State> for CosmicStack {
)
}
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {
if let Some((location, serial, time)) = self.last_location.lock().unwrap().clone() {
self.pointer_leave_if_previous(seat, data, serial, time, location);
}
if let Some(sessions) = self.active().user_data().get::<ScreencopySessions>() {
for session in &*sessions.0.borrow() {
session.cursor_leave(seat, InputType::Pointer)
}
}
PointerTarget::leave(
&self.windows.lock().unwrap()[self.active.load(Ordering::SeqCst)],
seat,

View file

@ -1,4 +1,6 @@
use crate::state::State;
use crate::{
state::State, utils::prelude::SeatExt, wayland::handlers::screencopy::ScreencopySessions,
};
use smithay::{
backend::{
input::KeyState,
@ -187,9 +189,30 @@ impl KeyboardTarget<State> for CosmicWindow {
impl PointerTarget<State> for CosmicWindow {
fn enter(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) {
use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_session_v1::InputType;
if let Some(sessions) = self.window.user_data().get::<ScreencopySessions>() {
for session in &*sessions.0.borrow() {
session.cursor_enter(seat, InputType::Pointer)
}
}
PointerTarget::enter(&self.window, seat, data, event)
}
fn motion(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) {
use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_session_v1::InputType;
if let Some(sessions) = self.window.user_data().get::<ScreencopySessions>() {
for session in &*sessions.0.borrow() {
let buffer_loc = (event.location.x, event.location.y); // we always screencast windows at 1x1 scale
if let Some((geo, hotspot)) =
seat.cursor_geometry(buffer_loc, &data.common.start_time)
{
session.cursor_info(seat, InputType::Pointer, geo, hotspot);
}
}
}
PointerTarget::motion(&self.window, seat, data, event)
}
fn button(&self, seat: &Seat<State>, data: &mut State, event: &ButtonEvent) {
@ -199,6 +222,14 @@ impl PointerTarget<State> for CosmicWindow {
PointerTarget::axis(&self.window, seat, data, frame)
}
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {
use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_session_v1::InputType;
if let Some(sessions) = self.window.user_data().get::<ScreencopySessions>() {
for session in &*sessions.0.borrow() {
session.cursor_leave(seat, InputType::Pointer)
}
}
PointerTarget::leave(&self.window, seat, data, serial, time)
}
}

View file

@ -13,13 +13,13 @@ use smithay::{
desktop::space::SpaceElement,
input::{
pointer::{
AxisFrame, ButtonEvent, Focus, GrabStartData as PointerGrabStartData, MotionEvent,
AxisFrame, ButtonEvent, GrabStartData as PointerGrabStartData, MotionEvent,
PointerGrab, PointerInnerHandle,
},
Seat,
},
output::Output,
utils::{IsAlive, Logical, Physical, Point, Rectangle, Scale, Serial},
utils::{IsAlive, Logical, Point, Serial},
};
use std::cell::RefCell;

View file

@ -189,11 +189,11 @@ impl FloatingLayout {
&mut self,
mapped: &CosmicMapped,
seat: &Seat<State>,
serial: Serial,
_serial: Serial,
start_data: PointerGrabStartData<State>,
edges: ResizeEdge,
) -> Option<ResizeSurfaceGrab> {
if let Some(pointer) = seat.get_pointer() {
if seat.get_pointer().is_some() {
let location = self.space.element_location(&mapped).unwrap();
let size = mapped.geometry().size;
@ -204,8 +204,6 @@ impl FloatingLayout {
location,
size,
))
//pointer.set_grab(state, grab, serial, Focus::Clear);
} else {
None
}

View file

@ -276,7 +276,7 @@ impl WorkspaceMode {
}
}
pub fn active_num(&self, output: &Output) -> usize {
fn active_num(&self, output: &Output) -> usize {
match self {
WorkspaceMode::Global(set) => set.active,
WorkspaceMode::OutputBound(sets) => {
@ -691,7 +691,7 @@ impl Shell {
}
}
pub fn outputs_for_surface<'a>(
pub fn visible_outputs_for_surface<'a>(
&'a self,
surface: &'a WlSurface,
) -> impl Iterator<Item = Output> + 'a {
@ -703,7 +703,7 @@ impl Shell {
Some(output) => {
Box::new(std::iter::once(output.clone())) as Box<dyn Iterator<Item = Output>>
}
None => Box::new(self.workspaces.spaces().flat_map(|w| {
None => Box::new(self.outputs().map(|o| self.active_space(o)).flat_map(|w| {
w.mapped()
.find(|e| e.has_surface(surface, WindowSurfaceType::ALL))
.into_iter()
@ -712,6 +712,47 @@ impl Shell {
}
}
pub fn workspaces_for_surface(
&self,
surface: &WlSurface,
) -> impl Iterator<Item = (WorkspaceHandle, Output)> {
match self.outputs.iter().find(|o| {
let map = layer_map_for_output(o);
map.layer_for_surface(surface, WindowSurfaceType::ALL)
.is_some()
}) {
Some(output) => self
.workspaces
.spaces()
.filter(move |workspace| {
workspace
.floating_layer
.space
.outputs()
.any(|o| o == output)
})
.map(|w| (w.handle.clone(), output.clone()))
.collect::<Vec<_>>(),
None => self
.workspaces
.spaces()
.filter_map(|w| {
if let Some(mapped) = w
.mapped()
.find(|e| e.has_surface(surface, WindowSurfaceType::ALL))
{
let outputs = w.outputs_for_element(mapped);
Some(std::iter::repeat(w.handle.clone()).zip(outputs).fuse())
} else {
None
}
})
.flatten()
.collect::<Vec<_>>(),
}
.into_iter()
}
pub fn element_for_surface(&self, surface: &WlSurface) -> Option<&CosmicMapped> {
self.workspaces
.spaces()
@ -730,6 +771,14 @@ impl Shell {
.find(|workspace| workspace.mapped().any(|m| m == mapped))
}
pub fn space_for_handle(&self, handle: &WorkspaceHandle) -> Option<&Workspace> {
self.workspaces.spaces().find(|w| &w.handle == handle)
}
pub fn space_for_handle_mut(&mut self, handle: &WorkspaceHandle) -> Option<&mut Workspace> {
self.workspaces.spaces_mut().find(|w| &w.handle == handle)
}
pub fn outputs(&self) -> impl Iterator<Item = &Output> {
self.outputs.iter()
}

View file

@ -1,14 +1,17 @@
use crate::{
shell::{
element::CosmicWindow,
layout::{
floating::{FloatingLayout, MoveSurfaceGrab},
tiling::TilingLayout,
},
shell::layout::{
floating::{FloatingLayout, MoveSurfaceGrab},
tiling::TilingLayout,
},
state::State,
utils::prelude::*,
wayland::protocols::workspace::WorkspaceHandle,
wayland::{
handlers::screencopy::DropableSession,
protocols::{
screencopy::{BufferParams, Session as ScreencopySession},
workspace::WorkspaceHandle,
},
},
};
use indexmap::IndexSet;
@ -17,21 +20,18 @@ use smithay::{
element::{surface::WaylandSurfaceRenderElement, AsRenderElements},
ImportAll, Renderer,
},
desktop::{
layer_map_for_output, space::SpaceElement, Kind, LayerSurface, Space, Window,
WindowSurfaceType,
},
desktop::{layer_map_for_output, space::SpaceElement, Kind, LayerSurface, Window},
input::{pointer::GrabStartData as PointerGrabStartData, Seat},
output::{Output, WeakOutput},
output::Output,
reexports::{
wayland_protocols::xdg::shell::server::xdg_toplevel::{self, ResizeEdge},
wayland_server::{protocol::wl_surface::WlSurface, DisplayHandle},
wayland_server::protocol::wl_surface::WlSurface,
},
render_elements,
utils::{IsAlive, Logical, Point, Rectangle, Scale, Serial},
wayland::shell::wlr_layer::Layer,
};
use std::{collections::HashMap, time::Duration};
use std::collections::HashMap;
use super::{
element::CosmicMapped,
@ -48,6 +48,8 @@ pub struct Workspace {
pub fullscreen: HashMap<Output, Window>,
pub handle: WorkspaceHandle,
pub focus_stack: FocusStacks,
pub pending_buffers: Vec<(ScreencopySession, BufferParams)>,
pub screencopy_sessions: Vec<DropableSession>,
}
#[derive(Debug, Default)]
@ -62,6 +64,8 @@ impl Workspace {
fullscreen: HashMap::new(),
handle,
focus_stack: FocusStacks::default(),
pending_buffers: Vec::new(),
screencopy_sessions: Vec::new(),
}
}