wip: screencopy
This commit is contained in:
parent
dd100d65e4
commit
5a4df346a8
26 changed files with 2046 additions and 327 deletions
|
|
@ -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!(),
|
||||
} {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue