tiling: Animate and enable/disable hints
This commit is contained in:
parent
4ea0136a9b
commit
adc28eeb93
11 changed files with 363 additions and 89 deletions
|
|
@ -10,11 +10,9 @@ use smithay::{
|
|||
};
|
||||
|
||||
#[cfg(feature = "debug")]
|
||||
use smithay::backend::renderer::{
|
||||
element::texture::TextureRenderElement, gles::GlesTexture, multigpu::Error as MultiError,
|
||||
};
|
||||
use smithay::backend::renderer::{element::texture::TextureRenderElement, gles::GlesTexture};
|
||||
|
||||
use super::{cursor::CursorRenderElement, GlMultiFrame, GlMultiRenderer};
|
||||
use super::{cursor::CursorRenderElement, GlMultiError, GlMultiFrame, GlMultiRenderer};
|
||||
|
||||
pub enum CosmicElement<R>
|
||||
where
|
||||
|
|
@ -167,7 +165,7 @@ impl<'a, 'b> RenderElement<GlMultiRenderer<'a, 'b>> for CosmicElement<GlMultiRen
|
|||
src: Rectangle<f64, BufferCoords>,
|
||||
dst: Rectangle<i32, Physical>,
|
||||
damage: &[Rectangle<i32, Physical>],
|
||||
) -> Result<(), <GlMultiRenderer<'a, 'b> as Renderer>::Error> {
|
||||
) -> Result<(), GlMultiError> {
|
||||
match self {
|
||||
CosmicElement::Workspace(elem) => elem.draw(frame, src, dst, damage),
|
||||
CosmicElement::Cursor(elem) => elem.draw(frame, src, dst, damage),
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ use crate::{
|
|||
shell::{
|
||||
element::window::CosmicWindowRenderElement, focus::target::WindowGroup,
|
||||
layout::floating::SeatMoveGrabState, CosmicMapped, CosmicMappedRenderElement,
|
||||
WorkspaceRenderElement,
|
||||
},
|
||||
state::{Common, Fps},
|
||||
utils::prelude::SeatExt,
|
||||
|
|
@ -44,7 +45,7 @@ use smithay::{
|
|||
UniformName, UniformType,
|
||||
},
|
||||
glow::GlowRenderer,
|
||||
multigpu::{gbm::GbmGlesBackend, MultiFrame, MultiRenderer},
|
||||
multigpu::{gbm::GbmGlesBackend, Error as MultiError, MultiFrame, MultiRenderer},
|
||||
Bind, Blit, ExportMem, ImportAll, ImportMem, Offscreen, Renderer, TextureFilter,
|
||||
},
|
||||
},
|
||||
|
|
@ -66,6 +67,7 @@ pub type GlMultiRenderer<'a, 'b> =
|
|||
MultiRenderer<'a, 'a, 'b, GbmGlesBackend<GlowRenderer>, GbmGlesBackend<GlowRenderer>>;
|
||||
pub type GlMultiFrame<'a, 'b, 'frame> =
|
||||
MultiFrame<'a, 'a, 'b, 'frame, GbmGlesBackend<GlowRenderer>, GbmGlesBackend<GlowRenderer>>;
|
||||
pub type GlMultiError = MultiError<GbmGlesBackend<GlowRenderer>, GbmGlesBackend<GlowRenderer>>;
|
||||
|
||||
pub static CLEAR_COLOR: [f32; 4] = [0.153, 0.161, 0.165, 1.0];
|
||||
pub static ACTIVE_GROUP_COLOR: [f32; 3] = [0.678, 0.635, 0.619];
|
||||
|
|
@ -298,6 +300,7 @@ where
|
|||
<R as Renderer>::Error: From<GlesError>,
|
||||
CosmicMappedRenderElement<R>: RenderElement<R>,
|
||||
CosmicWindowRenderElement<R>: RenderElement<R>,
|
||||
WorkspaceRenderElement<R>: RenderElement<R>,
|
||||
{
|
||||
#[cfg(feature = "debug")]
|
||||
puffin::profile_function!();
|
||||
|
|
@ -346,6 +349,7 @@ where
|
|||
.space_for_handle_mut(&handle)
|
||||
.ok_or(OutputNoMode)?
|
||||
.update_animations(&state.event_loop_handle);
|
||||
let overview = state.shell.overview_mode();
|
||||
let workspace = state.shell.space_for_handle(&handle).ok_or(OutputNoMode)?;
|
||||
let last_active_seat = state.last_active_seat().clone();
|
||||
let move_active = last_active_seat
|
||||
|
|
@ -365,7 +369,7 @@ where
|
|||
&state.shell.override_redirect_windows,
|
||||
state.xwayland_state.as_mut(),
|
||||
(!move_active && is_active_space).then_some(&last_active_seat),
|
||||
true,
|
||||
overview,
|
||||
state.config.static_conf.active_hint,
|
||||
exclude_workspace_overview,
|
||||
)
|
||||
|
|
@ -377,7 +381,7 @@ where
|
|||
Ok(elements)
|
||||
}
|
||||
|
||||
pub fn render_output<'frame, R, Target, OffTarget, Source>(
|
||||
pub fn render_output<R, Target, OffTarget, Source>(
|
||||
gpu: Option<&DrmNode>,
|
||||
renderer: &mut R,
|
||||
target: Target,
|
||||
|
|
@ -404,6 +408,7 @@ where
|
|||
CosmicElement<R>: RenderElement<R>,
|
||||
CosmicMappedRenderElement<R>: RenderElement<R>,
|
||||
CosmicWindowRenderElement<R>: RenderElement<R>,
|
||||
WorkspaceRenderElement<R>: RenderElement<R>,
|
||||
Source: Clone,
|
||||
{
|
||||
let handle = state.shell.workspaces.active(output).handle;
|
||||
|
|
@ -425,7 +430,7 @@ where
|
|||
result
|
||||
}
|
||||
|
||||
pub fn render_workspace<'frame, R, Target, OffTarget, Source>(
|
||||
pub fn render_workspace<R, Target, OffTarget, Source>(
|
||||
gpu: Option<&DrmNode>,
|
||||
renderer: &mut R,
|
||||
target: Target,
|
||||
|
|
@ -454,6 +459,7 @@ where
|
|||
CosmicElement<R>: RenderElement<R>,
|
||||
CosmicMappedRenderElement<R>: RenderElement<R>,
|
||||
CosmicWindowRenderElement<R>: RenderElement<R>,
|
||||
WorkspaceRenderElement<R>: RenderElement<R>,
|
||||
Source: Clone,
|
||||
{
|
||||
#[cfg(feature = "debug")]
|
||||
|
|
|
|||
|
|
@ -772,12 +772,12 @@ pub enum KeyModifier {
|
|||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct KeyModifiers {
|
||||
ctrl: bool,
|
||||
alt: bool,
|
||||
shift: bool,
|
||||
logo: bool,
|
||||
caps_lock: bool,
|
||||
num_lock: bool,
|
||||
pub ctrl: bool,
|
||||
pub alt: bool,
|
||||
pub shift: bool,
|
||||
pub logo: bool,
|
||||
pub caps_lock: bool,
|
||||
pub num_lock: bool,
|
||||
}
|
||||
|
||||
impl PartialEq<ModifiersState> for KeyModifiers {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::{
|
||||
config::{Action, Config},
|
||||
config::{Action, Config, KeyModifiers},
|
||||
shell::{
|
||||
focus::{target::PointerFocusTarget, FocusDirection},
|
||||
layout::{
|
||||
floating::SeatMoveGrabState,
|
||||
tiling::{Direction, FocusResult},
|
||||
},
|
||||
Workspace,
|
||||
OverviewMode, Workspace,
|
||||
}, // shell::grabs::SeatMoveGrabState
|
||||
state::Common,
|
||||
utils::prelude::*,
|
||||
|
|
@ -219,7 +219,7 @@ impl State {
|
|||
|
||||
let serial = SERIAL_COUNTER.next_serial();
|
||||
let time = Event::time_msec(&event);
|
||||
if let Some(action) = seat
|
||||
if let Some((action, mods)) = seat
|
||||
.get_keyboard()
|
||||
.unwrap()
|
||||
.input(
|
||||
|
|
@ -229,6 +229,18 @@ impl State {
|
|||
serial,
|
||||
time,
|
||||
|data, modifiers, handle| {
|
||||
if let OverviewMode::Started(action_modifiers, _) =
|
||||
data.common.shell.overview_mode()
|
||||
{
|
||||
if !(action_modifiers.ctrl && modifiers.ctrl)
|
||||
&& !(action_modifiers.alt && modifiers.alt)
|
||||
&& !(action_modifiers.logo && modifiers.logo)
|
||||
&& !(action_modifiers.shift && modifiers.shift)
|
||||
{
|
||||
data.common.shell.set_overview_mode(None);
|
||||
}
|
||||
}
|
||||
|
||||
if state == KeyState::Released
|
||||
&& userdata.get::<SupressedKeys>().unwrap().filter(&handle)
|
||||
{
|
||||
|
|
@ -283,9 +295,10 @@ impl State {
|
|||
.get::<SupressedKeys>()
|
||||
.unwrap()
|
||||
.add(&handle);
|
||||
return FilterResult::Intercept(Some(
|
||||
return FilterResult::Intercept(Some((
|
||||
action.clone(),
|
||||
));
|
||||
binding.modifiers.clone(),
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -295,7 +308,7 @@ impl State {
|
|||
)
|
||||
.flatten()
|
||||
{
|
||||
self.handle_action(action, seat, serial, time)
|
||||
self.handle_action(action, seat, serial, time, mods)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -640,7 +653,14 @@ impl State {
|
|||
}
|
||||
}
|
||||
|
||||
fn handle_action(&mut self, action: Action, seat: &Seat<State>, serial: Serial, time: u32) {
|
||||
fn handle_action(
|
||||
&mut self,
|
||||
action: Action,
|
||||
seat: &Seat<State>,
|
||||
serial: Serial,
|
||||
time: u32,
|
||||
mods: KeyModifiers,
|
||||
) {
|
||||
match action {
|
||||
Action::Terminate => {
|
||||
self.common.should_stop = true;
|
||||
|
|
@ -920,17 +940,21 @@ impl State {
|
|||
FocusResult::None => {
|
||||
// TODO: Handle Workspace orientation
|
||||
match focus {
|
||||
FocusDirection::Left => {
|
||||
self.handle_action(Action::PreviousWorkspace, seat, serial, time)
|
||||
}
|
||||
FocusDirection::Left => self.handle_action(
|
||||
Action::PreviousWorkspace,
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
mods,
|
||||
),
|
||||
FocusDirection::Right => {
|
||||
self.handle_action(Action::NextWorkspace, seat, serial, time)
|
||||
self.handle_action(Action::NextWorkspace, seat, serial, time, mods)
|
||||
}
|
||||
FocusDirection::Up => {
|
||||
self.handle_action(Action::PreviousOutput, seat, serial, time)
|
||||
self.handle_action(Action::PreviousOutput, seat, serial, time, mods)
|
||||
}
|
||||
FocusDirection::Down => {
|
||||
self.handle_action(Action::NextOutput, seat, serial, time)
|
||||
self.handle_action(Action::NextOutput, seat, serial, time, mods)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -955,17 +979,36 @@ impl State {
|
|||
// TODO: Handle Workspace orientation
|
||||
// TODO: Being able to move Groups (move_further should be KeyboardFocusTarget instead)
|
||||
match direction {
|
||||
Direction::Left => {
|
||||
self.handle_action(Action::MoveToPreviousWorkspace, seat, serial, time)
|
||||
}
|
||||
Direction::Right => {
|
||||
self.handle_action(Action::MoveToNextWorkspace, seat, serial, time)
|
||||
}
|
||||
Direction::Up => {
|
||||
self.handle_action(Action::MoveToPreviousOutput, seat, serial, time)
|
||||
}
|
||||
Direction::Left => self.handle_action(
|
||||
Action::MoveToPreviousWorkspace,
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
mods,
|
||||
),
|
||||
Direction::Right => self.handle_action(
|
||||
Action::MoveToNextWorkspace,
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
mods,
|
||||
),
|
||||
Direction::Up => self.handle_action(
|
||||
Action::MoveToPreviousOutput,
|
||||
seat,
|
||||
serial,
|
||||
time,
|
||||
mods,
|
||||
),
|
||||
Direction::Down => {
|
||||
self.handle_action(Action::MoveToNextOutput, seat, serial, time)
|
||||
self.handle_action(Action::MoveToNextOutput, seat, serial, time, mods)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let focus_stack = workspace.focus_stack.get(seat);
|
||||
if let Some(focused_window) = focus_stack.last() {
|
||||
if workspace.is_tiled(focused_window) {
|
||||
self.common.shell.set_overview_mode(Some(mods));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
backend::render::{
|
||||
element::{AsGlowFrame, AsGlowRenderer},
|
||||
GlMultiFrame, GlMultiRenderer,
|
||||
GlMultiError, GlMultiFrame, GlMultiRenderer,
|
||||
},
|
||||
state::State,
|
||||
utils::prelude::SeatExt,
|
||||
|
|
@ -17,7 +17,6 @@ use smithay::{
|
|||
},
|
||||
gles::element::PixelShaderElement,
|
||||
glow::GlowRenderer,
|
||||
multigpu::Error as MultiError,
|
||||
ImportAll, ImportMem, Renderer,
|
||||
},
|
||||
},
|
||||
|
|
@ -859,7 +858,7 @@ impl<'a, 'b> RenderElement<GlMultiRenderer<'a, 'b>>
|
|||
src: Rectangle<f64, BufferCoords>,
|
||||
dst: Rectangle<i32, Physical>,
|
||||
damage: &[Rectangle<i32, Physical>],
|
||||
) -> Result<(), <GlMultiRenderer<'a, 'b> as Renderer>::Error> {
|
||||
) -> Result<(), GlMultiError> {
|
||||
match self {
|
||||
CosmicMappedRenderElement::Stack(elem) => elem.draw(frame, src, dst, damage),
|
||||
CosmicMappedRenderElement::Window(elem) => elem.draw(frame, src, dst, damage),
|
||||
|
|
@ -867,13 +866,13 @@ impl<'a, 'b> RenderElement<GlMultiRenderer<'a, 'b>>
|
|||
CosmicMappedRenderElement::TiledWindow(elem) => elem.draw(frame, src, dst, damage),
|
||||
CosmicMappedRenderElement::Indicator(elem) => {
|
||||
RenderElement::<GlowRenderer>::draw(elem, frame.glow_frame_mut(), src, dst, damage)
|
||||
.map_err(|err| MultiError::Render(err))
|
||||
.map_err(|err| GlMultiError::Render(err))
|
||||
}
|
||||
#[cfg(feature = "debug")]
|
||||
CosmicMappedRenderElement::Egui(elem) => {
|
||||
let glow_frame = frame.glow_frame_mut();
|
||||
RenderElement::<GlowRenderer>::draw(elem, glow_frame, src, dst, damage)
|
||||
.map_err(|err| MultiError::Render(err))
|
||||
.map_err(|err| GlMultiError::Render(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
backend::render::{
|
||||
element::{AsGlowFrame, AsGlowRenderer},
|
||||
GlMultiFrame, GlMultiRenderer,
|
||||
GlMultiError, GlMultiFrame, GlMultiRenderer,
|
||||
},
|
||||
shell::Shell,
|
||||
state::State,
|
||||
|
|
@ -24,7 +24,6 @@ use smithay::{
|
|||
AsRenderElements, Element, Id, RenderElement,
|
||||
},
|
||||
glow::GlowRenderer,
|
||||
multigpu::Error as MultiError,
|
||||
utils::CommitCounter,
|
||||
ImportAll, ImportMem, Renderer,
|
||||
},
|
||||
|
|
@ -683,11 +682,11 @@ impl<'a, 'b> RenderElement<GlMultiRenderer<'a, 'b>>
|
|||
src: Rectangle<f64, smithay::utils::Buffer>,
|
||||
dst: Rectangle<i32, Physical>,
|
||||
damage: &[Rectangle<i32, Physical>],
|
||||
) -> Result<(), <GlMultiRenderer<'a, 'b> as Renderer>::Error> {
|
||||
) -> Result<(), GlMultiError> {
|
||||
match self {
|
||||
CosmicWindowRenderElement::Header(h) => h
|
||||
.draw(frame.glow_frame_mut(), src, dst, damage)
|
||||
.map_err(|err| MultiError::Render(err)),
|
||||
.map_err(|err| GlMultiError::Render(err)),
|
||||
CosmicWindowRenderElement::Window(w) => w.draw(frame, src, dst, damage),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -351,6 +351,7 @@ impl FloatingLayout {
|
|||
output: &Output,
|
||||
focused: Option<&CosmicMapped>,
|
||||
indicator_thickness: u8,
|
||||
alpha: f32,
|
||||
) -> Vec<CosmicMappedRenderElement<R>>
|
||||
where
|
||||
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
|
||||
|
|
@ -374,7 +375,7 @@ impl FloatingLayout {
|
|||
renderer,
|
||||
render_location.to_physical_precise_round(output_scale),
|
||||
output_scale.into(),
|
||||
1.0,
|
||||
alpha,
|
||||
);
|
||||
if focused == Some(elem) {
|
||||
if indicator_thickness > 0 {
|
||||
|
|
@ -386,7 +387,7 @@ impl FloatingLayout {
|
|||
elem.geometry().size,
|
||||
),
|
||||
indicator_thickness,
|
||||
1.0,
|
||||
alpha,
|
||||
FOCUS_INDICATOR_COLOR,
|
||||
);
|
||||
elements.insert(0, element.into());
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use crate::{
|
|||
},
|
||||
grabs::ResizeEdge,
|
||||
layout::Orientation,
|
||||
CosmicSurface, OutputNotMapped,
|
||||
CosmicSurface, OutputNotMapped, OverviewMode,
|
||||
},
|
||||
utils::prelude::*,
|
||||
wayland::{
|
||||
|
|
@ -52,7 +52,7 @@ mod grabs;
|
|||
pub use self::blocker::*;
|
||||
pub use self::grabs::*;
|
||||
|
||||
const ANIMATION_DURATION: Duration = Duration::from_millis(200);
|
||||
pub const ANIMATION_DURATION: Duration = Duration::from_millis(200);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct OutputData {
|
||||
|
|
@ -1439,7 +1439,7 @@ impl TilingLayout {
|
|||
output: &Output,
|
||||
focused: Option<&CosmicMapped>,
|
||||
non_exclusive_zone: Rectangle<i32, Logical>,
|
||||
draw_groups: bool,
|
||||
overview: OverviewMode,
|
||||
indicator_thickness: u8,
|
||||
) -> Result<Vec<CosmicMappedRenderElement<R>>, OutputNotMapped>
|
||||
where
|
||||
|
|
@ -1478,12 +1478,32 @@ impl TilingLayout {
|
|||
} else {
|
||||
1.0
|
||||
};
|
||||
let draw_groups = match overview {
|
||||
OverviewMode::Started(_, start) => {
|
||||
let percentage = (Instant::now().duration_since(start).as_millis() as f32
|
||||
/ ANIMATION_DURATION.as_millis() as f32)
|
||||
.min(1.0);
|
||||
Some(Ease::Cubic(Cubic::Out).tween(percentage))
|
||||
}
|
||||
OverviewMode::Ended(end) => {
|
||||
let percentage = (1.0
|
||||
- Instant::now().duration_since(end).as_millis() as f32
|
||||
/ ANIMATION_DURATION.as_millis() as f32)
|
||||
.max(0.0);
|
||||
if percentage > 0.0 {
|
||||
Some(Ease::Cubic(Cubic::Out).tween(percentage))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
OverviewMode::None => None,
|
||||
};
|
||||
|
||||
let mut elements = Vec::new();
|
||||
|
||||
// all gone windows and fade them out
|
||||
let old_geometries = if let Some(reference_tree) = reference_tree.as_ref() {
|
||||
let (geometries, _) = if draw_groups {
|
||||
let (geometries, _) = if let Some(transition) = draw_groups {
|
||||
geometries_for_groupview(
|
||||
reference_tree,
|
||||
renderer,
|
||||
|
|
@ -1491,6 +1511,7 @@ impl TilingLayout {
|
|||
focused, // TODO: Would be better to be an old focus,
|
||||
// but for that we have to associate focus with a tree (and animate focus changes properly)
|
||||
1.0 - percentage,
|
||||
transition,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
|
|
@ -1512,13 +1533,14 @@ impl TilingLayout {
|
|||
None
|
||||
};
|
||||
|
||||
let (geometries, group_elements) = if draw_groups {
|
||||
let (geometries, group_elements) = if let Some(transition) = draw_groups {
|
||||
geometries_for_groupview(
|
||||
target_tree,
|
||||
renderer,
|
||||
non_exclusive_zone,
|
||||
focused,
|
||||
percentage,
|
||||
transition,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
|
|
@ -1540,7 +1562,16 @@ impl TilingLayout {
|
|||
focused,
|
||||
output_scale,
|
||||
percentage,
|
||||
if draw_groups { 3 } else { indicator_thickness },
|
||||
if let Some(transition) = draw_groups {
|
||||
let diff = (3u8.abs_diff(indicator_thickness) as f32 * transition).round() as u8;
|
||||
if 3 > indicator_thickness {
|
||||
indicator_thickness + diff
|
||||
} else {
|
||||
indicator_thickness - diff
|
||||
}
|
||||
} else {
|
||||
indicator_thickness
|
||||
},
|
||||
));
|
||||
|
||||
Ok(elements)
|
||||
|
|
@ -1553,6 +1584,7 @@ fn geometries_for_groupview<R>(
|
|||
non_exclusive_zone: Rectangle<i32, Logical>,
|
||||
focused: Option<&CosmicMapped>,
|
||||
alpha: f32,
|
||||
transition: f32,
|
||||
) -> Option<(
|
||||
HashMap<NodeId, Rectangle<i32, Logical>>,
|
||||
Vec<CosmicMappedRenderElement<R>>,
|
||||
|
|
@ -1570,11 +1602,14 @@ where
|
|||
let mut geometries = HashMap::new();
|
||||
|
||||
const GAP: i32 = 16;
|
||||
let gap: i32 = (GAP as f32 * transition).round() as i32;
|
||||
let alpha = alpha * transition;
|
||||
|
||||
for node_id in tree.traverse_pre_order_ids(root).unwrap() {
|
||||
if let Some(mut geo) = stack.pop() {
|
||||
// zoom in windows
|
||||
geo.loc += (GAP, GAP).into();
|
||||
geo.size -= (GAP * 2, GAP * 2).into();
|
||||
geo.loc += (gap, gap).into();
|
||||
geo.size -= (gap * 2, gap * 2).into();
|
||||
|
||||
let node: &Node<Data> = tree.get(&node_id).unwrap();
|
||||
let data = node.data();
|
||||
|
|
@ -1715,8 +1750,8 @@ where
|
|||
.into(),
|
||||
);
|
||||
|
||||
geo.loc += (GAP, GAP).into();
|
||||
geo.size -= (GAP * 2, GAP * 2).into();
|
||||
geo.loc += (gap, gap).into();
|
||||
geo.size -= (gap * 2, gap * 2).into();
|
||||
}
|
||||
|
||||
geometries.insert(node_id.clone(), geo);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use calloop::LoopHandle;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{cell::RefCell, collections::HashMap};
|
||||
use std::{cell::RefCell, collections::HashMap, time::Instant};
|
||||
use tracing::warn;
|
||||
|
||||
use cosmic_protocols::workspace::v1::server::zcosmic_workspace_handle_v1::State as WState;
|
||||
|
|
@ -29,7 +29,7 @@ use smithay::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
config::{Config, OutputConfig, WorkspaceMode as ConfigMode},
|
||||
config::{Config, KeyModifiers, OutputConfig, WorkspaceMode as ConfigMode},
|
||||
utils::prelude::*,
|
||||
wayland::protocols::{
|
||||
toplevel_info::ToplevelInfoState,
|
||||
|
|
@ -52,9 +52,19 @@ use self::{
|
|||
element::CosmicWindow,
|
||||
focus::target::KeyboardFocusTarget,
|
||||
grabs::ResizeEdge,
|
||||
layout::{floating::FloatingLayout, tiling::TilingLayout},
|
||||
layout::{
|
||||
floating::FloatingLayout,
|
||||
tiling::{TilingLayout, ANIMATION_DURATION},
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum OverviewMode {
|
||||
None,
|
||||
Started(KeyModifiers, Instant),
|
||||
Ended(Instant),
|
||||
}
|
||||
|
||||
pub struct Shell {
|
||||
pub popups: PopupManager,
|
||||
pub outputs: Vec<Output>,
|
||||
|
|
@ -72,6 +82,7 @@ pub struct Shell {
|
|||
pub workspace_state: WorkspaceState<State>,
|
||||
|
||||
gaps: (u8, u8),
|
||||
overview_mode: OverviewMode,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -498,6 +509,7 @@ impl Shell {
|
|||
workspace_state,
|
||||
|
||||
gaps: config.static_conf.gaps,
|
||||
overview_mode: OverviewMode::None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1038,9 +1050,11 @@ impl Shell {
|
|||
}
|
||||
|
||||
pub fn animations_going(&self) -> bool {
|
||||
self.workspaces
|
||||
.spaces()
|
||||
.any(|workspace| workspace.animations_going())
|
||||
matches!(self.overview_mode, OverviewMode::None)
|
||||
|| self
|
||||
.workspaces
|
||||
.spaces()
|
||||
.any(|workspace| workspace.animations_going())
|
||||
}
|
||||
|
||||
pub fn update_animations(&mut self, handle: &LoopHandle<'static, crate::state::Data>) {
|
||||
|
|
@ -1049,6 +1063,28 @@ impl Shell {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn set_overview_mode(&mut self, enabled: Option<KeyModifiers>) {
|
||||
if let Some(modifiers) = enabled {
|
||||
if !matches!(self.overview_mode, OverviewMode::Started(_, _)) {
|
||||
self.overview_mode = OverviewMode::Started(modifiers, Instant::now());
|
||||
}
|
||||
} else {
|
||||
if !matches!(self.overview_mode, OverviewMode::Ended(_)) {
|
||||
self.overview_mode = OverviewMode::Ended(Instant::now());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn overview_mode(&mut self) -> OverviewMode {
|
||||
if let OverviewMode::Ended(timestamp) = self.overview_mode {
|
||||
if Instant::now().duration_since(timestamp) > ANIMATION_DURATION {
|
||||
self.overview_mode = OverviewMode::None;
|
||||
}
|
||||
}
|
||||
|
||||
self.overview_mode.clone()
|
||||
}
|
||||
|
||||
pub fn refresh(&mut self) {
|
||||
#[cfg(feature = "debug")]
|
||||
puffin::profile_function!();
|
||||
|
|
@ -1235,7 +1271,7 @@ impl Shell {
|
|||
}
|
||||
}
|
||||
let elements = from_workspace.mapped().cloned().collect::<Vec<_>>();
|
||||
std::mem::drop(from_workspace);
|
||||
|
||||
for mapped in elements.into_iter() {
|
||||
state.common.shell.update_reactive_popups(&mapped);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
use crate::{
|
||||
backend::render::element::AsGlowRenderer,
|
||||
shell::layout::{
|
||||
floating::{FloatingLayout, MoveSurfaceGrab},
|
||||
tiling::TilingLayout,
|
||||
backend::render::{
|
||||
element::{AsGlowFrame, AsGlowRenderer},
|
||||
GlMultiError, GlMultiFrame, GlMultiRenderer,
|
||||
},
|
||||
shell::{
|
||||
layout::{
|
||||
floating::{FloatingLayout, MoveSurfaceGrab},
|
||||
tiling::{TilingLayout, ANIMATION_DURATION},
|
||||
},
|
||||
OverviewMode,
|
||||
},
|
||||
state::State,
|
||||
utils::prelude::*,
|
||||
|
|
@ -20,19 +26,30 @@ use crate::{
|
|||
use calloop::LoopHandle;
|
||||
use indexmap::IndexSet;
|
||||
use smithay::{
|
||||
backend::renderer::{
|
||||
element::{surface::WaylandSurfaceRenderElement, AsRenderElements, Element, RenderElement},
|
||||
ImportAll, ImportMem, Renderer,
|
||||
backend::{
|
||||
allocator::Fourcc,
|
||||
renderer::{
|
||||
element::{
|
||||
surface::WaylandSurfaceRenderElement, texture::TextureRenderElement,
|
||||
AsRenderElements, Element, Id, RenderElement,
|
||||
},
|
||||
gles::{GlesError, GlesTexture},
|
||||
glow::{GlowFrame, GlowRenderer},
|
||||
ImportAll, ImportMem, Renderer,
|
||||
},
|
||||
},
|
||||
desktop::{layer_map_for_output, space::SpaceElement, LayerSurface},
|
||||
input::{pointer::GrabStartData as PointerGrabStartData, Seat},
|
||||
output::Output,
|
||||
reexports::wayland_server::protocol::wl_surface::WlSurface,
|
||||
utils::{Buffer as BufferCoords, IsAlive, Logical, Physical, Point, Rectangle, Scale, Size},
|
||||
utils::{
|
||||
Buffer as BufferCoords, IsAlive, Logical, Physical, Point, Rectangle, Scale, Size,
|
||||
Transform,
|
||||
},
|
||||
wayland::{seat::WaylandFocus, shell::wlr_layer::Layer},
|
||||
xwayland::X11Surface,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::{collections::HashMap, time::Instant};
|
||||
use tracing::warn;
|
||||
|
||||
use super::{
|
||||
|
|
@ -454,7 +471,7 @@ impl Workspace {
|
|||
override_redirect_windows: &[X11Surface],
|
||||
xwm_state: Option<&'a mut XWaylandState>,
|
||||
draw_focus_indicator: Option<&Seat<State>>,
|
||||
draw_groups: bool,
|
||||
overview: OverviewMode,
|
||||
indicator_thickness: u8,
|
||||
exclude_workspace_overview: bool,
|
||||
) -> Result<Vec<WorkspaceRenderElement<R>>, OutputNotMapped>
|
||||
|
|
@ -463,6 +480,7 @@ impl Workspace {
|
|||
<R as Renderer>::TextureId: 'static,
|
||||
CosmicMappedRenderElement<R>: RenderElement<R>,
|
||||
CosmicWindowRenderElement<R>: RenderElement<R>,
|
||||
WorkspaceRenderElement<R>: RenderElement<R>,
|
||||
{
|
||||
#[cfg(feature = "debug")]
|
||||
puffin::profile_function!();
|
||||
|
|
@ -540,7 +558,7 @@ impl Workspace {
|
|||
} else {
|
||||
// TODO: Handle modes like
|
||||
// - keyboard window swapping
|
||||
// - resizing / moving in tiling
|
||||
// - resizing in tiling
|
||||
|
||||
// overlay and top layer surfaces
|
||||
let lower = {
|
||||
|
|
@ -595,9 +613,31 @@ impl Workspace {
|
|||
let focused =
|
||||
draw_focus_indicator.and_then(|seat| self.focus_stack.get(seat).last().cloned());
|
||||
// floating surfaces
|
||||
let alpha = match &overview {
|
||||
OverviewMode::Started(_, started) => {
|
||||
(1.0 - (Instant::now().duration_since(*started).as_millis()
|
||||
/ ANIMATION_DURATION.as_millis()) as f32)
|
||||
.max(0.0)
|
||||
* 0.4
|
||||
+ 0.6
|
||||
}
|
||||
OverviewMode::Ended(ended) => {
|
||||
((Instant::now().duration_since(*ended).as_millis()
|
||||
/ ANIMATION_DURATION.as_millis()) as f32)
|
||||
* 0.4
|
||||
+ 0.6
|
||||
}
|
||||
OverviewMode::None => 1.0,
|
||||
};
|
||||
render_elements.extend(
|
||||
self.floating_layer
|
||||
.render_output::<R>(renderer, output, focused.as_ref(), indicator_thickness)
|
||||
.render_output::<R>(
|
||||
renderer,
|
||||
output,
|
||||
focused.as_ref(),
|
||||
indicator_thickness,
|
||||
alpha,
|
||||
)
|
||||
.into_iter()
|
||||
.map(WorkspaceRenderElement::from),
|
||||
);
|
||||
|
|
@ -610,7 +650,7 @@ impl Workspace {
|
|||
output,
|
||||
focused.as_ref(),
|
||||
layer_map.non_exclusive_zone(),
|
||||
draw_groups,
|
||||
overview.clone(),
|
||||
indicator_thickness,
|
||||
)?
|
||||
.into_iter()
|
||||
|
|
@ -629,6 +669,64 @@ impl Workspace {
|
|||
}
|
||||
}
|
||||
|
||||
if let OverviewMode::Started(_, start) = overview {
|
||||
let alpha = Instant::now().duration_since(start).as_millis() as f64 / 100.0;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct BackdropTexture(Id, GlesTexture);
|
||||
|
||||
if renderer
|
||||
.glow_renderer()
|
||||
.egl_context()
|
||||
.user_data()
|
||||
.get::<BackdropTexture>()
|
||||
.is_none()
|
||||
{
|
||||
let tex = BackdropTexture(
|
||||
Id::new(),
|
||||
renderer
|
||||
.glow_renderer_mut()
|
||||
.import_memory(&[0, 0, 0, 255], Fourcc::Argb8888, (1, 1).into(), false)
|
||||
.unwrap(),
|
||||
);
|
||||
renderer
|
||||
.glow_renderer()
|
||||
.egl_context()
|
||||
.user_data()
|
||||
.insert_if_missing(|| tex);
|
||||
};
|
||||
let BackdropTexture(id, tex) = renderer
|
||||
.glow_renderer()
|
||||
.egl_context()
|
||||
.user_data()
|
||||
.get::<BackdropTexture>()
|
||||
.unwrap()
|
||||
.clone();
|
||||
|
||||
render_elements.push(
|
||||
TextureRenderElement::from_static_texture(
|
||||
id,
|
||||
renderer.id(),
|
||||
(0.0, 0.0),
|
||||
tex,
|
||||
1,
|
||||
smithay::utils::Transform::Normal,
|
||||
Some(alpha as f32),
|
||||
Some(Rectangle::from_loc_and_size((0., 0.), (1., 1.))),
|
||||
Some(output.geometry().size),
|
||||
if alpha >= 1.0 {
|
||||
Some(vec![Rectangle::from_loc_and_size(
|
||||
(0, 0),
|
||||
output.geometry().size.to_buffer(1, Transform::Normal),
|
||||
)])
|
||||
} else {
|
||||
None
|
||||
},
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
// bottom and background layer surfaces
|
||||
{
|
||||
render_elements.extend(
|
||||
|
|
@ -675,6 +773,7 @@ where
|
|||
{
|
||||
Wayland(WaylandSurfaceRenderElement<R>),
|
||||
Window(CosmicMappedRenderElement<R>),
|
||||
Backdrop(TextureRenderElement<GlesTexture>),
|
||||
}
|
||||
|
||||
impl<R> Element for WorkspaceRenderElement<R>
|
||||
|
|
@ -686,6 +785,7 @@ where
|
|||
match self {
|
||||
WorkspaceRenderElement::Wayland(elem) => elem.id(),
|
||||
WorkspaceRenderElement::Window(elem) => elem.id(),
|
||||
WorkspaceRenderElement::Backdrop(elem) => elem.id(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -693,6 +793,7 @@ where
|
|||
match self {
|
||||
WorkspaceRenderElement::Wayland(elem) => elem.current_commit(),
|
||||
WorkspaceRenderElement::Window(elem) => elem.current_commit(),
|
||||
WorkspaceRenderElement::Backdrop(elem) => elem.current_commit(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -700,6 +801,7 @@ where
|
|||
match self {
|
||||
WorkspaceRenderElement::Wayland(elem) => elem.src(),
|
||||
WorkspaceRenderElement::Window(elem) => elem.src(),
|
||||
WorkspaceRenderElement::Backdrop(elem) => elem.src(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -707,6 +809,7 @@ where
|
|||
match self {
|
||||
WorkspaceRenderElement::Wayland(elem) => elem.geometry(scale),
|
||||
WorkspaceRenderElement::Window(elem) => elem.geometry(scale),
|
||||
WorkspaceRenderElement::Backdrop(elem) => elem.geometry(scale),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -714,6 +817,7 @@ where
|
|||
match self {
|
||||
WorkspaceRenderElement::Wayland(elem) => elem.location(scale),
|
||||
WorkspaceRenderElement::Window(elem) => elem.location(scale),
|
||||
WorkspaceRenderElement::Backdrop(elem) => elem.location(scale),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -721,6 +825,7 @@ where
|
|||
match self {
|
||||
WorkspaceRenderElement::Wayland(elem) => elem.transform(),
|
||||
WorkspaceRenderElement::Window(elem) => elem.transform(),
|
||||
WorkspaceRenderElement::Backdrop(elem) => elem.transform(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -732,6 +837,7 @@ where
|
|||
match self {
|
||||
WorkspaceRenderElement::Wayland(elem) => elem.damage_since(scale, commit),
|
||||
WorkspaceRenderElement::Window(elem) => elem.damage_since(scale, commit),
|
||||
WorkspaceRenderElement::Backdrop(elem) => elem.damage_since(scale, commit),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -739,6 +845,7 @@ where
|
|||
match self {
|
||||
WorkspaceRenderElement::Wayland(elem) => elem.opaque_regions(scale),
|
||||
WorkspaceRenderElement::Window(elem) => elem.opaque_regions(scale),
|
||||
WorkspaceRenderElement::Backdrop(elem) => elem.opaque_regions(scale),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -746,36 +853,70 @@ where
|
|||
match self {
|
||||
WorkspaceRenderElement::Wayland(elem) => elem.alpha(),
|
||||
WorkspaceRenderElement::Window(elem) => elem.alpha(),
|
||||
WorkspaceRenderElement::Backdrop(elem) => elem.alpha(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> RenderElement<R> for WorkspaceRenderElement<R>
|
||||
where
|
||||
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
|
||||
<R as Renderer>::TextureId: 'static,
|
||||
CosmicMappedRenderElement<R>: RenderElement<R>,
|
||||
{
|
||||
impl RenderElement<GlowRenderer> for WorkspaceRenderElement<GlowRenderer> {
|
||||
fn draw<'frame>(
|
||||
&self,
|
||||
frame: &mut <R as Renderer>::Frame<'frame>,
|
||||
frame: &mut GlowFrame<'frame>,
|
||||
src: Rectangle<f64, BufferCoords>,
|
||||
dst: Rectangle<i32, Physical>,
|
||||
damage: &[Rectangle<i32, smithay::utils::Physical>],
|
||||
) -> Result<(), <R as Renderer>::Error> {
|
||||
) -> Result<(), GlesError> {
|
||||
match self {
|
||||
WorkspaceRenderElement::Wayland(elem) => elem.draw(frame, src, dst, damage),
|
||||
WorkspaceRenderElement::Window(elem) => elem.draw(frame, src, dst, damage),
|
||||
WorkspaceRenderElement::Backdrop(elem) => {
|
||||
RenderElement::<GlowRenderer>::draw(elem, frame, src, dst, damage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn underlying_storage(
|
||||
&self,
|
||||
renderer: &mut R,
|
||||
renderer: &mut GlowRenderer,
|
||||
) -> Option<smithay::backend::renderer::element::UnderlyingStorage> {
|
||||
match self {
|
||||
WorkspaceRenderElement::Wayland(elem) => elem.underlying_storage(renderer),
|
||||
WorkspaceRenderElement::Window(elem) => elem.underlying_storage(renderer),
|
||||
WorkspaceRenderElement::Backdrop(elem) => elem.underlying_storage(renderer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> RenderElement<GlMultiRenderer<'a, 'b>>
|
||||
for WorkspaceRenderElement<GlMultiRenderer<'a, 'b>>
|
||||
{
|
||||
fn draw<'frame>(
|
||||
&self,
|
||||
frame: &mut GlMultiFrame<'a, 'b, 'frame>,
|
||||
src: Rectangle<f64, BufferCoords>,
|
||||
dst: Rectangle<i32, Physical>,
|
||||
damage: &[Rectangle<i32, smithay::utils::Physical>],
|
||||
) -> Result<(), GlMultiError> {
|
||||
match self {
|
||||
WorkspaceRenderElement::Wayland(elem) => elem.draw(frame, src, dst, damage),
|
||||
WorkspaceRenderElement::Window(elem) => elem.draw(frame, src, dst, damage),
|
||||
WorkspaceRenderElement::Backdrop(elem) => {
|
||||
RenderElement::<GlowRenderer>::draw(elem, frame.glow_frame_mut(), src, dst, damage)
|
||||
.map_err(GlMultiError::Render)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn underlying_storage(
|
||||
&self,
|
||||
renderer: &mut GlMultiRenderer<'a, 'b>,
|
||||
) -> Option<smithay::backend::renderer::element::UnderlyingStorage> {
|
||||
match self {
|
||||
WorkspaceRenderElement::Wayland(elem) => elem.underlying_storage(renderer),
|
||||
WorkspaceRenderElement::Window(elem) => elem.underlying_storage(renderer),
|
||||
WorkspaceRenderElement::Backdrop(elem) => {
|
||||
elem.underlying_storage(renderer.glow_renderer_mut())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -801,3 +942,14 @@ where
|
|||
WorkspaceRenderElement::Window(elem)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> From<TextureRenderElement<GlesTexture>> for WorkspaceRenderElement<R>
|
||||
where
|
||||
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
|
||||
<R as Renderer>::TextureId: 'static,
|
||||
CosmicMappedRenderElement<R>: RenderElement<R>,
|
||||
{
|
||||
fn from(elem: TextureRenderElement<GlesTexture>) -> Self {
|
||||
WorkspaceRenderElement::Backdrop(elem)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,10 @@ use crate::{
|
|||
element::{AsGlowRenderer, CosmicElement},
|
||||
render_output, render_workspace, CursorMode, CLEAR_COLOR,
|
||||
},
|
||||
shell::{element::window::CosmicWindowRenderElement, CosmicMappedRenderElement, CosmicSurface},
|
||||
shell::{
|
||||
element::window::CosmicWindowRenderElement, CosmicMappedRenderElement, CosmicSurface,
|
||||
WorkspaceRenderElement,
|
||||
},
|
||||
state::{BackendData, ClientState, Common, Data, State},
|
||||
utils::prelude::OutputExt,
|
||||
wayland::protocols::{
|
||||
|
|
@ -663,6 +666,7 @@ pub fn render_output_to_buffer(
|
|||
CosmicElement<R>: RenderElement<R>,
|
||||
CosmicMappedRenderElement<R>: RenderElement<R>,
|
||||
CosmicWindowRenderElement<R>: RenderElement<R>,
|
||||
WorkspaceRenderElement<R>: RenderElement<R>,
|
||||
{
|
||||
let cursor_mode = match session.cursor_mode() {
|
||||
ScreencopyCursorMode::Embedded => CursorMode::All,
|
||||
|
|
@ -795,6 +799,7 @@ pub fn render_workspace_to_buffer(
|
|||
CosmicElement<R>: RenderElement<R>,
|
||||
CosmicMappedRenderElement<R>: RenderElement<R>,
|
||||
CosmicWindowRenderElement<R>: RenderElement<R>,
|
||||
WorkspaceRenderElement<R>: RenderElement<R>,
|
||||
{
|
||||
let cursor_mode = match session.cursor_mode() {
|
||||
ScreencopyCursorMode::Embedded => CursorMode::All,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue