2023-12-27 21:51:42 +04:00
|
|
|
use std::cmp::max;
|
|
|
|
|
use std::rc::Rc;
|
|
|
|
|
use std::time::Duration;
|
|
|
|
|
|
|
|
|
|
use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement};
|
2024-04-10 08:53:35 +04:00
|
|
|
use smithay::backend::renderer::element::utils::RescaleRenderElement;
|
2024-02-07 11:32:02 +04:00
|
|
|
use smithay::backend::renderer::element::{Element, Kind};
|
2024-04-09 22:37:10 +04:00
|
|
|
use smithay::backend::renderer::gles::GlesRenderer;
|
2023-12-28 08:45:12 +04:00
|
|
|
use smithay::utils::{Logical, Point, Rectangle, Scale, Size};
|
2023-12-27 21:51:42 +04:00
|
|
|
|
2024-02-21 21:27:44 +04:00
|
|
|
use super::focus_ring::{FocusRing, FocusRingRenderElement};
|
2024-04-10 08:53:35 +04:00
|
|
|
use super::{LayoutElement, LayoutElementRenderElement, Options};
|
2024-02-07 17:05:15 +04:00
|
|
|
use crate::animation::Animation;
|
2024-02-05 14:05:08 +04:00
|
|
|
use crate::niri_render_elements;
|
2024-02-07 11:32:02 +04:00
|
|
|
use crate::render_helpers::offscreen::OffscreenRenderElement;
|
2024-04-10 08:53:35 +04:00
|
|
|
use crate::render_helpers::primary_gpu_texture::PrimaryGpuTextureRenderElement;
|
2024-02-06 11:24:50 +04:00
|
|
|
use crate::render_helpers::renderer::NiriRenderer;
|
2024-04-10 08:53:35 +04:00
|
|
|
use crate::render_helpers::{RenderSnapshot, RenderTarget, ToRenderElement};
|
2023-12-27 21:51:42 +04:00
|
|
|
|
|
|
|
|
/// Toplevel window with decorations.
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct Tile<W: LayoutElement> {
|
|
|
|
|
/// The toplevel window itself.
|
|
|
|
|
window: W,
|
|
|
|
|
|
|
|
|
|
/// The border around the window.
|
|
|
|
|
border: FocusRing,
|
|
|
|
|
|
2024-02-06 19:47:36 +04:00
|
|
|
/// The focus ring around the window.
|
|
|
|
|
///
|
|
|
|
|
/// It's supposed to be on the Workspace, but for the sake of a nicer open animation it's
|
|
|
|
|
/// currently here.
|
|
|
|
|
focus_ring: FocusRing,
|
|
|
|
|
|
2023-12-27 21:51:42 +04:00
|
|
|
/// Whether this tile is fullscreen.
|
|
|
|
|
///
|
|
|
|
|
/// This will update only when the `window` actually goes fullscreen, rather than right away,
|
|
|
|
|
/// to avoid black backdrop flicker before the window has had a chance to resize.
|
|
|
|
|
is_fullscreen: bool,
|
|
|
|
|
|
|
|
|
|
/// The black backdrop for fullscreen windows.
|
|
|
|
|
fullscreen_backdrop: SolidColorBuffer,
|
|
|
|
|
|
|
|
|
|
/// The size we were requested to fullscreen into.
|
|
|
|
|
fullscreen_size: Size<i32, Logical>,
|
|
|
|
|
|
2024-02-07 11:32:02 +04:00
|
|
|
/// The animation upon opening a window.
|
|
|
|
|
open_animation: Option<Animation>,
|
|
|
|
|
|
2023-12-27 21:51:42 +04:00
|
|
|
/// Configurable properties of the layout.
|
|
|
|
|
options: Rc<Options>,
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-05 14:05:08 +04:00
|
|
|
niri_render_elements! {
|
2024-02-21 09:05:41 +04:00
|
|
|
TileRenderElement<R> => {
|
2024-02-05 14:05:08 +04:00
|
|
|
LayoutElement = LayoutElementRenderElement<R>,
|
2024-02-21 21:27:44 +04:00
|
|
|
FocusRing = FocusRingRenderElement,
|
2024-02-21 11:08:48 +04:00
|
|
|
SolidColor = SolidColorRenderElement,
|
2024-02-07 11:32:02 +04:00
|
|
|
Offscreen = RescaleRenderElement<OffscreenRenderElement>,
|
2024-02-05 14:05:08 +04:00
|
|
|
}
|
2024-02-04 22:52:11 +04:00
|
|
|
}
|
|
|
|
|
|
2024-04-09 22:37:10 +04:00
|
|
|
niri_render_elements! {
|
|
|
|
|
TileSnapshotRenderElement => {
|
2024-04-10 08:53:35 +04:00
|
|
|
Texture = PrimaryGpuTextureRenderElement,
|
2024-04-09 22:37:10 +04:00
|
|
|
FocusRing = FocusRingRenderElement,
|
|
|
|
|
SolidColor = SolidColorRenderElement,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-27 21:51:42 +04:00
|
|
|
impl<W: LayoutElement> Tile<W> {
|
|
|
|
|
pub fn new(window: W, options: Rc<Options>) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
window,
|
2024-02-12 09:34:54 +04:00
|
|
|
border: FocusRing::new(options.border.into()),
|
2024-02-06 19:47:36 +04:00
|
|
|
focus_ring: FocusRing::new(options.focus_ring),
|
2023-12-27 21:51:42 +04:00
|
|
|
is_fullscreen: false, // FIXME: up-to-date fullscreen right away, but we need size.
|
|
|
|
|
fullscreen_backdrop: SolidColorBuffer::new((0, 0), [0., 0., 0., 1.]),
|
|
|
|
|
fullscreen_size: Default::default(),
|
2024-02-07 11:32:02 +04:00
|
|
|
open_animation: None,
|
2023-12-27 21:51:42 +04:00
|
|
|
options,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn update_config(&mut self, options: Rc<Options>) {
|
2024-02-12 09:34:54 +04:00
|
|
|
self.border.update_config(options.border.into());
|
2024-02-06 19:47:36 +04:00
|
|
|
self.focus_ring.update_config(options.focus_ring);
|
2023-12-27 21:51:42 +04:00
|
|
|
self.options = options;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-28 10:49:31 +04:00
|
|
|
pub fn update_window(&mut self) {
|
|
|
|
|
// FIXME: remove when we can get a fullscreen size right away.
|
|
|
|
|
if self.fullscreen_size != Size::from((0, 0)) {
|
|
|
|
|
self.is_fullscreen = self.window.is_fullscreen();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-07 11:32:02 +04:00
|
|
|
pub fn advance_animations(&mut self, current_time: Duration, is_active: bool) {
|
2024-03-19 18:22:25 +04:00
|
|
|
let draw_border_with_background = self
|
|
|
|
|
.window
|
|
|
|
|
.rules()
|
|
|
|
|
.draw_border_with_background
|
|
|
|
|
.unwrap_or_else(|| !self.window.has_ssd());
|
2024-02-21 11:08:48 +04:00
|
|
|
self.border
|
2024-03-19 18:22:25 +04:00
|
|
|
.update(self.window.size(), !draw_border_with_background);
|
2023-12-27 21:51:42 +04:00
|
|
|
self.border.set_active(is_active);
|
2024-02-06 19:47:36 +04:00
|
|
|
|
2024-03-19 18:22:25 +04:00
|
|
|
let draw_focus_ring_with_background = if self.effective_border_width().is_some() {
|
|
|
|
|
false
|
|
|
|
|
} else {
|
|
|
|
|
draw_border_with_background
|
|
|
|
|
};
|
|
|
|
|
self.focus_ring
|
|
|
|
|
.update(self.tile_size(), !draw_focus_ring_with_background);
|
2024-02-06 19:47:36 +04:00
|
|
|
self.focus_ring.set_active(is_active);
|
2024-02-07 11:32:02 +04:00
|
|
|
|
|
|
|
|
match &mut self.open_animation {
|
|
|
|
|
Some(anim) => {
|
|
|
|
|
anim.set_current_time(current_time);
|
|
|
|
|
if anim.is_done() {
|
|
|
|
|
self.open_animation = None;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
None => (),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn are_animations_ongoing(&self) -> bool {
|
|
|
|
|
self.open_animation.is_some()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn start_open_animation(&mut self) {
|
2024-02-07 17:05:15 +04:00
|
|
|
self.open_animation = Some(Animation::new(
|
|
|
|
|
0.,
|
|
|
|
|
1.,
|
2024-03-05 13:32:30 +04:00
|
|
|
0.,
|
2024-02-07 17:05:15 +04:00
|
|
|
self.options.animations.window_open,
|
|
|
|
|
niri_config::Animation::default_window_open(),
|
|
|
|
|
));
|
2023-12-27 21:51:42 +04:00
|
|
|
}
|
|
|
|
|
|
2024-04-09 22:37:10 +04:00
|
|
|
pub fn open_animation(&self) -> &Option<Animation> {
|
|
|
|
|
&self.open_animation
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-27 21:51:42 +04:00
|
|
|
pub fn window(&self) -> &W {
|
|
|
|
|
&self.window
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-19 14:41:17 +04:00
|
|
|
pub fn window_mut(&mut self) -> &mut W {
|
|
|
|
|
&mut self.window
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-27 21:51:42 +04:00
|
|
|
pub fn into_window(self) -> W {
|
|
|
|
|
self.window
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns `None` if the border is hidden and `Some(width)` if it should be shown.
|
|
|
|
|
fn effective_border_width(&self) -> Option<i32> {
|
|
|
|
|
if self.is_fullscreen {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if self.border.is_off() {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Some(self.border.width())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the location of the window's visual geometry within this Tile.
|
2023-12-28 08:14:35 +04:00
|
|
|
pub fn window_loc(&self) -> Point<i32, Logical> {
|
2023-12-27 21:51:42 +04:00
|
|
|
let mut loc = Point::from((0, 0));
|
|
|
|
|
|
|
|
|
|
// In fullscreen, center the window in the given size.
|
|
|
|
|
if self.is_fullscreen {
|
|
|
|
|
let window_size = self.window.size();
|
|
|
|
|
let target_size = self.fullscreen_size;
|
|
|
|
|
|
|
|
|
|
// Windows aren't supposed to be larger than the fullscreen size, but in case we get
|
|
|
|
|
// one, leave it at the top-left as usual.
|
|
|
|
|
if window_size.w < target_size.w {
|
|
|
|
|
loc.x += (target_size.w - window_size.w) / 2;
|
|
|
|
|
}
|
|
|
|
|
if window_size.h < target_size.h {
|
|
|
|
|
loc.y += (target_size.h - window_size.h) / 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if let Some(width) = self.effective_border_width() {
|
|
|
|
|
loc += (width, width).into();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
loc
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn tile_size(&self) -> Size<i32, Logical> {
|
|
|
|
|
let mut size = self.window.size();
|
|
|
|
|
|
|
|
|
|
if self.is_fullscreen {
|
|
|
|
|
// Normally we'd just return the fullscreen size here, but this makes things a bit
|
|
|
|
|
// nicer if a fullscreen window is bigger than the fullscreen size for some reason.
|
|
|
|
|
size.w = max(size.w, self.fullscreen_size.w);
|
|
|
|
|
size.h = max(size.h, self.fullscreen_size.h);
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if let Some(width) = self.effective_border_width() {
|
2023-12-28 18:53:08 +04:00
|
|
|
size.w = size.w.saturating_add(width * 2);
|
|
|
|
|
size.h = size.h.saturating_add(width * 2);
|
2023-12-27 21:51:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn window_size(&self) -> Size<i32, Logical> {
|
|
|
|
|
self.window.size()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn buf_loc(&self) -> Point<i32, Logical> {
|
|
|
|
|
let mut loc = Point::from((0, 0));
|
|
|
|
|
loc += self.window_loc();
|
|
|
|
|
loc += self.window.buf_loc();
|
|
|
|
|
loc
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn is_in_input_region(&self, mut point: Point<f64, Logical>) -> bool {
|
|
|
|
|
point -= self.window_loc().to_f64();
|
|
|
|
|
self.window.is_in_input_region(point)
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-28 08:45:12 +04:00
|
|
|
pub fn is_in_activation_region(&self, point: Point<f64, Logical>) -> bool {
|
|
|
|
|
let activation_region = Rectangle::from_loc_and_size((0, 0), self.tile_size());
|
|
|
|
|
activation_region.to_f64().contains(point)
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-27 21:51:42 +04:00
|
|
|
pub fn request_tile_size(&mut self, mut size: Size<i32, Logical>) {
|
|
|
|
|
// Can't go through effective_border_width() because we might be fullscreen.
|
|
|
|
|
if !self.border.is_off() {
|
|
|
|
|
let width = self.border.width();
|
|
|
|
|
size.w = max(1, size.w - width * 2);
|
|
|
|
|
size.h = max(1, size.h - width * 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.window.request_size(size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn tile_width_for_window_width(&self, size: i32) -> i32 {
|
|
|
|
|
if self.border.is_off() {
|
|
|
|
|
size
|
|
|
|
|
} else {
|
2023-12-28 18:53:08 +04:00
|
|
|
size.saturating_add(self.border.width() * 2)
|
2023-12-27 21:51:42 +04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn tile_height_for_window_height(&self, size: i32) -> i32 {
|
|
|
|
|
if self.border.is_off() {
|
|
|
|
|
size
|
|
|
|
|
} else {
|
2023-12-28 18:53:08 +04:00
|
|
|
size.saturating_add(self.border.width() * 2)
|
2023-12-27 21:51:42 +04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn window_height_for_tile_height(&self, size: i32) -> i32 {
|
|
|
|
|
if self.border.is_off() {
|
|
|
|
|
size
|
|
|
|
|
} else {
|
2023-12-29 11:38:01 +04:00
|
|
|
size.saturating_sub(self.border.width() * 2)
|
2023-12-27 21:51:42 +04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn request_fullscreen(&mut self, size: Size<i32, Logical>) {
|
|
|
|
|
self.fullscreen_backdrop.resize(size);
|
|
|
|
|
self.fullscreen_size = size;
|
|
|
|
|
self.window.request_fullscreen(size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn min_size(&self) -> Size<i32, Logical> {
|
|
|
|
|
let mut size = self.window.min_size();
|
|
|
|
|
|
|
|
|
|
if let Some(width) = self.effective_border_width() {
|
|
|
|
|
size.w = max(1, size.w);
|
|
|
|
|
size.h = max(1, size.h);
|
2023-12-28 18:53:08 +04:00
|
|
|
|
|
|
|
|
size.w = size.w.saturating_add(width * 2);
|
|
|
|
|
size.h = size.h.saturating_add(width * 2);
|
2023-12-27 21:51:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn max_size(&self) -> Size<i32, Logical> {
|
|
|
|
|
let mut size = self.window.max_size();
|
|
|
|
|
|
|
|
|
|
if let Some(width) = self.effective_border_width() {
|
|
|
|
|
if size.w > 0 {
|
2023-12-28 18:53:08 +04:00
|
|
|
size.w = size.w.saturating_add(width * 2);
|
2023-12-27 21:51:42 +04:00
|
|
|
}
|
|
|
|
|
if size.h > 0 {
|
2023-12-28 18:53:08 +04:00
|
|
|
size.h = size.h.saturating_add(width * 2);
|
2023-12-27 21:51:42 +04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-19 18:22:25 +04:00
|
|
|
pub fn draw_border_with_background(&self) -> bool {
|
|
|
|
|
if self.effective_border_width().is_some() {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.window
|
|
|
|
|
.rules()
|
|
|
|
|
.draw_border_with_background
|
|
|
|
|
.unwrap_or_else(|| !self.window.has_ssd())
|
2023-12-27 21:51:42 +04:00
|
|
|
}
|
|
|
|
|
|
2024-02-07 11:32:02 +04:00
|
|
|
fn render_inner<R: NiriRenderer>(
|
2023-12-27 21:51:42 +04:00
|
|
|
&self,
|
|
|
|
|
renderer: &mut R,
|
|
|
|
|
location: Point<i32, Logical>,
|
|
|
|
|
scale: Scale<f64>,
|
2024-02-21 21:27:44 +04:00
|
|
|
view_size: Size<i32, Logical>,
|
2024-02-06 19:47:36 +04:00
|
|
|
focus_ring: bool,
|
2024-03-24 09:03:59 +04:00
|
|
|
target: RenderTarget,
|
2024-02-05 14:05:08 +04:00
|
|
|
) -> impl Iterator<Item = TileRenderElement<R>> {
|
2024-03-24 08:30:26 +04:00
|
|
|
let alpha = if self.is_fullscreen {
|
|
|
|
|
1.
|
|
|
|
|
} else {
|
|
|
|
|
self.window.rules().opacity.unwrap_or(1.).clamp(0., 1.)
|
|
|
|
|
};
|
|
|
|
|
|
2024-02-05 07:58:33 +04:00
|
|
|
let rv = self
|
|
|
|
|
.window
|
2024-03-24 09:03:59 +04:00
|
|
|
.render(renderer, location + self.window_loc(), scale, alpha, target)
|
2024-02-05 07:58:33 +04:00
|
|
|
.into_iter()
|
|
|
|
|
.map(Into::into);
|
|
|
|
|
|
2024-02-21 11:08:48 +04:00
|
|
|
let elem = self.effective_border_width().map(|width| {
|
|
|
|
|
self.border
|
2024-02-21 21:27:44 +04:00
|
|
|
.render(
|
|
|
|
|
renderer,
|
|
|
|
|
location + Point::from((width, width)),
|
|
|
|
|
scale,
|
|
|
|
|
view_size,
|
|
|
|
|
)
|
2024-02-21 11:08:48 +04:00
|
|
|
.map(Into::into)
|
2024-02-05 07:58:33 +04:00
|
|
|
});
|
|
|
|
|
let rv = rv.chain(elem.into_iter().flatten());
|
|
|
|
|
|
2024-02-21 21:27:44 +04:00
|
|
|
let elem = focus_ring.then(|| {
|
|
|
|
|
self.focus_ring
|
|
|
|
|
.render(renderer, location, scale, view_size)
|
|
|
|
|
.map(Into::into)
|
|
|
|
|
});
|
2024-02-06 19:47:36 +04:00
|
|
|
let rv = rv.chain(elem.into_iter().flatten());
|
|
|
|
|
|
2024-02-05 07:58:33 +04:00
|
|
|
let elem = self.is_fullscreen.then(|| {
|
2024-02-21 11:08:48 +04:00
|
|
|
SolidColorRenderElement::from_buffer(
|
2023-12-27 21:51:42 +04:00
|
|
|
&self.fullscreen_backdrop,
|
|
|
|
|
location.to_physical_precise_round(scale),
|
|
|
|
|
scale,
|
|
|
|
|
1.,
|
|
|
|
|
Kind::Unspecified,
|
2024-02-21 11:08:48 +04:00
|
|
|
)
|
|
|
|
|
.into()
|
2024-02-05 07:58:33 +04:00
|
|
|
});
|
|
|
|
|
rv.chain(elem)
|
2023-12-27 21:51:42 +04:00
|
|
|
}
|
2024-02-07 11:32:02 +04:00
|
|
|
|
|
|
|
|
pub fn render<R: NiriRenderer>(
|
|
|
|
|
&self,
|
|
|
|
|
renderer: &mut R,
|
|
|
|
|
location: Point<i32, Logical>,
|
|
|
|
|
scale: Scale<f64>,
|
2024-02-21 21:27:44 +04:00
|
|
|
view_size: Size<i32, Logical>,
|
2024-02-07 11:32:02 +04:00
|
|
|
focus_ring: bool,
|
2024-03-24 09:03:59 +04:00
|
|
|
target: RenderTarget,
|
2024-02-07 11:32:02 +04:00
|
|
|
) -> impl Iterator<Item = TileRenderElement<R>> {
|
|
|
|
|
if let Some(anim) = &self.open_animation {
|
|
|
|
|
let renderer = renderer.as_gles_renderer();
|
2024-03-24 09:03:59 +04:00
|
|
|
let elements =
|
|
|
|
|
self.render_inner(renderer, location, scale, view_size, focus_ring, target);
|
2024-02-07 11:32:02 +04:00
|
|
|
let elements = elements.collect::<Vec<TileRenderElement<_>>>();
|
|
|
|
|
|
|
|
|
|
let elem = OffscreenRenderElement::new(
|
|
|
|
|
renderer,
|
|
|
|
|
scale.x as i32,
|
|
|
|
|
&elements,
|
2024-03-05 10:33:25 +04:00
|
|
|
anim.value().clamp(0., 1.) as f32,
|
2024-02-07 11:32:02 +04:00
|
|
|
);
|
|
|
|
|
self.window()
|
|
|
|
|
.set_offscreen_element_id(Some(elem.id().clone()));
|
|
|
|
|
|
|
|
|
|
let mut center = location;
|
|
|
|
|
center.x += self.tile_size().w / 2;
|
|
|
|
|
center.y += self.tile_size().h / 2;
|
|
|
|
|
|
|
|
|
|
Some(TileRenderElement::Offscreen(
|
|
|
|
|
RescaleRenderElement::from_element(
|
|
|
|
|
elem,
|
|
|
|
|
center.to_physical_precise_round(scale),
|
2024-03-05 10:33:25 +04:00
|
|
|
(anim.value() / 2. + 0.5).max(0.),
|
2024-02-07 11:32:02 +04:00
|
|
|
),
|
|
|
|
|
))
|
|
|
|
|
.into_iter()
|
|
|
|
|
.chain(None.into_iter().flatten())
|
|
|
|
|
} else {
|
|
|
|
|
self.window().set_offscreen_element_id(None);
|
|
|
|
|
|
2024-03-24 09:03:59 +04:00
|
|
|
let elements =
|
|
|
|
|
self.render_inner(renderer, location, scale, view_size, focus_ring, target);
|
2024-02-07 11:32:02 +04:00
|
|
|
None.into_iter().chain(Some(elements).into_iter().flatten())
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-04-09 22:37:10 +04:00
|
|
|
|
2024-04-10 09:26:56 +04:00
|
|
|
fn render_snapshot<E, C>(
|
2024-04-09 22:37:10 +04:00
|
|
|
&self,
|
|
|
|
|
renderer: &mut GlesRenderer,
|
|
|
|
|
scale: Scale<f64>,
|
|
|
|
|
view_size: Size<i32, Logical>,
|
2024-04-10 08:53:35 +04:00
|
|
|
contents: Vec<C>,
|
|
|
|
|
) -> Vec<TileSnapshotRenderElement>
|
|
|
|
|
where
|
2024-04-10 09:26:56 +04:00
|
|
|
E: Into<TileSnapshotRenderElement>,
|
|
|
|
|
C: ToRenderElement<RenderElement = E>,
|
2024-04-10 08:53:35 +04:00
|
|
|
{
|
|
|
|
|
let alpha = if self.is_fullscreen {
|
|
|
|
|
1.
|
|
|
|
|
} else {
|
|
|
|
|
self.window.rules().opacity.unwrap_or(1.).clamp(0., 1.)
|
|
|
|
|
};
|
2024-04-09 22:37:10 +04:00
|
|
|
|
2024-04-10 08:53:35 +04:00
|
|
|
let mut rv = vec![];
|
2024-04-09 22:37:10 +04:00
|
|
|
|
2024-04-10 08:53:35 +04:00
|
|
|
for baked in contents {
|
|
|
|
|
let elem = baked.to_render_element(self.window_loc(), scale, alpha, Kind::Unspecified);
|
|
|
|
|
rv.push(elem.into());
|
|
|
|
|
}
|
2024-04-09 22:37:10 +04:00
|
|
|
|
2024-04-10 08:53:35 +04:00
|
|
|
if let Some(width) = self.effective_border_width() {
|
|
|
|
|
rv.extend(
|
|
|
|
|
self.border
|
|
|
|
|
.render(renderer, Point::from((width, width)), scale, view_size)
|
|
|
|
|
.map(Into::into),
|
|
|
|
|
);
|
|
|
|
|
}
|
2024-04-09 22:37:10 +04:00
|
|
|
|
2024-04-10 08:53:35 +04:00
|
|
|
if self.is_fullscreen {
|
|
|
|
|
let elem = SolidColorRenderElement::from_buffer(
|
|
|
|
|
&self.fullscreen_backdrop,
|
|
|
|
|
Point::from((0, 0)),
|
|
|
|
|
scale,
|
|
|
|
|
1.,
|
|
|
|
|
Kind::Unspecified,
|
|
|
|
|
);
|
|
|
|
|
rv.push(elem.into());
|
|
|
|
|
}
|
2024-04-09 22:37:10 +04:00
|
|
|
|
2024-04-10 08:53:35 +04:00
|
|
|
rv
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn take_snapshot_for_close_anim(
|
|
|
|
|
&self,
|
|
|
|
|
renderer: &mut GlesRenderer,
|
|
|
|
|
scale: Scale<f64>,
|
|
|
|
|
view_size: Size<i32, Logical>,
|
|
|
|
|
) -> RenderSnapshot<TileSnapshotRenderElement, TileSnapshotRenderElement> {
|
|
|
|
|
let snapshot = self.window.take_last_render();
|
|
|
|
|
if snapshot.contents.is_empty() {
|
|
|
|
|
return RenderSnapshot::default();
|
|
|
|
|
}
|
2024-04-09 22:37:10 +04:00
|
|
|
|
|
|
|
|
RenderSnapshot {
|
2024-04-10 08:53:35 +04:00
|
|
|
contents: self.render_snapshot(renderer, scale, view_size, snapshot.contents),
|
|
|
|
|
blocked_out_contents: self.render_snapshot(
|
|
|
|
|
renderer,
|
|
|
|
|
scale,
|
|
|
|
|
view_size,
|
|
|
|
|
snapshot.blocked_out_contents,
|
|
|
|
|
),
|
2024-04-09 22:37:10 +04:00
|
|
|
block_out_from: snapshot.block_out_from,
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-12-27 21:51:42 +04:00
|
|
|
}
|